重学STM32---(十) ——CAN通信(二)
CAN协议是非常难的,但是在stm32中却是简单的,只需要我们配置寄存器即可,,,即使这样,我在学习的时候也遇到了许多困难
1.开时钟,不用说
2.设置GPIO口,,CAN_TX复用推挽输出,CAN_RX上拉或浮空输入
3.CAN初始化了,分三步
(1) 一般设置
/*对CAN初始化*/
CAN1->MCR |= 1 << 15; //软复位
CAN1->MCR &= ~(1 << 1); //退出睡眠模式 (郁闷,忘退出睡眠模式了,折腾了半天)
CAN1->MCR |= 1 << 0; //设置初始化模式 必须
while(!(CAN1->MSR & 1 << 0)); //等待确认初始化
CAN1->MCR |= 0 << 7; //禁止时间触发模式
CAN1->MCR |= 0 << 6; //禁止自动离线
CAN1->MCR |= 0 << 5; //禁止自动唤醒
CAN1->MCR |= 1 << 4; //报文只传送一次,禁止自动重传
CAN1->MCR |= 0 << 2; //优先级由报文的标识符决定
(2)时序设置(时序也在初始化模式中)
/* 设置CAN位时序*/
CAN1->BTR &= 0x00000000; //
CAN1->BTR |= mode << 30; //正常模式(0)或环回模式(1)可见CAN_BTR寄存器
CAN1->BTR |= sjw << 24; //设置sjw
CAN1->BTR |= ts2 << 20; //
CAN1->BTR |= ts1 << 16; //
CAN1->BTR |= brp << 0;
CAN1->MCR &= ~(1 << 0); //退出初始化
while(CAN1->MSR & 1 << 0); //确认退出初始化
(3)滤波器设置、
/* 设置过滤器组 */
CAN1->FMR |= 1 << 0; //过滤器组设置在初始化模式(记得必须设置初始化模式)
CAN1->FA1R &= ~(1 << 0); //过滤器禁用
CAN1->FM1R &= ~(1<< 0); //过滤器组工作在标识符屏蔽位模式
CAN1->FS1R |= 1<<0; //过滤器组位宽为32位
CAN1->FFA1R &= ~(1 << 0); //关联到fifo0
CAN1->sFilterRegister[0].FR1 = 0X00000000; //全都为0 ,什么数据都接受
CAN1->sFilterRegister[0].FR2 = 0X00000000;
CAN1->FA1R |= 1 << 0; //激活过滤器
CAN1->FMR &= 0 << 0; //退出滤波器初始化模式 (记得要退出,否则发送成功却接受不到,不要问我为什么这么清楚。。。)
4.发送消息函数和得到发送状态函数
见下写程序
u8 CAN_TX_Msg(u8 ide, u32 id, u8 rtr, u8 len, u8 *data)
u8 CAN_TX_Statt(u8 mbox) 5.接收函数
void CAN_RX_Msg(u8 *ide, u32* id, u8* rtr, u8* len, u8 *data, u8 fifox) (参数要用指针,开始我ide没用指针,在其他函数调用这个函数ide的值是不确定的)
{
*ide = (CAN1->sFIFOMailBox[fifox].RIR & 1<<2)>>2;
if(*ide == 0)
{
*id = CAN1->sFIFOMailBox[fifox].RIR >> 21;
}
else
{
*id = CAN1->sFIFOMailBox[fifox].RIR >> 3;
}
*rtr = (CAN1->sFIFOMailBox[fifox].RIR & 1<<1)>>1;
*len = CAN1->sFIFOMailBox[fifox].RDTR & 0x0f;
//接收数据
data[0]=CAN1->sFIFOMailBox[fifox].RDLR&0XFF;
data[1]=(CAN1->sFIFOMailBox[fifox].RDLR>>8)&0XFF;
data[2]=(CAN1->sFIFOMailBox[fifox].RDLR>>16)&0XFF;
data[3]=(CAN1->sFIFOMailBox[fifox].RDLR>>24)&0XFF;
data[4]=CAN1->sFIFOMailBox[fifox].RDHR&0XFF;
data[5]=(CAN1->sFIFOMailBox[fifox].RDHR>>8)&0XFF;
data[6]=(CAN1->sFIFOMailBox[fifox].RDHR>>16)&0XFF;
data[7]=(CAN1->sFIFOMailBox[fifox].RDHR>>24)&0XFF;
if(fifox==0)CAN1->RF0R|=0X20;//释放FIFO0邮箱
else if(fifox==1)CAN1->RF1R|=0X20;//释放FIFO1邮箱
}
其他的见下函数(只有一块开发板,只能测试回环模式)
主函数
u8 txBuff[] ;
int main()
{
u8 key,time = ;
u8 i;
u8 data = ;
u8 reBuff[];
Stm32_Clock_Init(); //系统时钟设置
uart_init(,); //串口初始化为115200
delay_init(); //延时初始化
LED_Init(); //初始化与LED连接的硬件接口
LCD_Init();
KEY_Init();
LCD_ShowString(,,,,,"CAN回环模式实验");
LCD_ShowString(,,,,,"KEY1:发送数据");
CAN_Init(,,,,);
)
{
key = KEY_Scan(); //查询按键
if(key == KEY1) //按键1发送数据
{
; i < ; i++)
txBuff[i] = data++;
CAN_Send_Msg((u8*)txBuff, );
// delay_ms(10);
if(CAN_Receive_Msg(reBuff))
{
; i < ; i++)
{
printf ("CAN发送数据为:%d\r\n\r\n", reBuff[i]);
txBuff[i] = ;
// LCD_ShowxNum(10 + i*10, 100,reBuff[i], 3, 16, 0x80);
}
}
}
time++;
delay_ms();
)
{
LED0 = !LED0 ;
time = ;
}
}
}
#include "can.h"
//#include "stm32f10x.h"
#include "sys.h"
#define CAN_INT_ENABLE 0
void CAN_Init(u8 sjw, u8 ts2, u8 ts1,u16 brp, u8 mode)
{
sjw -= ;
ts1 -= ;
ts2 -= ;
brp -= ;
/*开启CAN_TX与CAN_RX的时钟PB*/
RCC->APB2ENR |= << ;
/*开启CAN时钟*/
RCC->APB1ENR |= << ;
/*设置PB11上拉输入,PB12推挽输出*/
GPIOB->CRH &= ~();
GPIOB->CRH |= ;
GPIOB->ODR |= <<;
/*对CAN初始化*/
CAN1->MCR |= << ; //软复位
CAN1->MCR &= ~( << );
CAN1->MCR |= << ; //设置初始化模式
<< )); //等待确认初始化
CAN1->MCR |= << ; //禁止时间触发模式
CAN1->MCR |= << ; //禁止自动离线
CAN1->MCR |= << ; //禁止自动唤醒
CAN1->MCR |= << ; //报文只传送一次,禁止自动重传
CAN1->MCR |= << ; //优先级由报文的标识符决定
/* 设置CAN位时序*/
CAN1->BTR &= 0x00000000; //
CAN1->BTR |= mode << ; //正常模式或环回模式
CAN1->BTR |= sjw << ; //设置sjw
CAN1->BTR |= ts2 << ; //
CAN1->BTR |= ts1 << ; //
CAN1->BTR |= brp << ;
CAN1->MCR &= ~( << ); //退出初始化
<< ); //确认退出初始化
/* 设置过滤器组 */
CAN1->FMR |= << ; //过滤器组设置在初始化模式
CAN1->FA1R &= ~( << ); //过滤器禁用
CAN1->FM1R &= ~(<< ); //过滤器组工作在标识符屏蔽位模式
CAN1->FS1R |= <<; //过滤器组位宽为32位
CAN1->FFA1R &= ~( << ); //关联到fifo0
CAN1->sFilterRegister[].FR1 = 0X00000000; //全都为0 ,什么数据都接受
CAN1->sFilterRegister[].FR2 = 0X00000000;
CAN1->FA1R |= << ; //激活过滤器
CAN1->FMR &= << ; //退出滤波器初始化模式
#if CAN_INT_ENABLE
CAN1->IER |= << ; //FIFO0消息挂号中断使能
MY_NVIC_Init(,,USB_LP_CAN1_RX0_IRQn,);
#endif
}
ide 0:标准帧 1:扩展帧id 标识idrtr 0:数据帧 1:远程帧len 数据长度*data 指向要发送数据的指针
u8 CAN_TX_Msg(u8 ide, u32 id, u8 rtr, u8 len, u8 *data)
{
u8 mbox;
<<) mbox = ; //邮箱0为空
<<) mbox = ;
<<) mbox = ;
else return 0xff;
/*为标准id时*/
)
{
id = id & 0x07ff; //取11位
id <<= ;
}
/*为扩展ID时*/
)
{
id <<= ;
}
CAN1->sTxMailBox[mbox].TIR = ;
CAN1->sTxMailBox[mbox].TIR |= ide << ; //
CAN1->sTxMailBox[mbox].TIR |= id ; //
CAN1->sTxMailBox[mbox].TIR &= ~(<<); //
CAN1->sTxMailBox[mbox].TDTR |= len&0xf; //
CAN1->sTxMailBox[mbox].TDLR =((u32)data[]) | ((u32)data[]<<) | ((u32)data[]<<) | ((u32)data[]<<);
CAN1->sTxMailBox[mbox].TDHR =((u32)data[]) | ((u32)data[]<<) | ((u32)data[]<<) | ((u32)data[]<<);
CAN1->sTxMailBox[mbox].TIR |= << ;
return mbox ;
}
//判断发送是成功
//state = 7成功
u8 CAN_TX_Statt(u8 mbox)
{
u8 state;
switch(mbox)
{
:
state |= (CAN1->TSR & <<) | (CAN1->TSR & <<) |((CAN1->TSR & <<)>>);
break ;
:
state |= (CAN1->TSR & <<)>>;
state |= (CAN1->TSR & <<)>>;
state |= (CAN1->TSR & <<)>>;
break ;
:
state |= (CAN1->TSR & <<)>>;
state |= (CAN1->TSR & <<)>>;
state |= (CAN1->TSR & <<)>>;
break ;
default :
state = 0x05;
}
return state ;
}
//得到在FIFO0/FIFO1中接收到的报文个数.
//fifox:0/1.FIFO编号;
//返回值:FIFO0/FIFO1中的报文个数.
u8 CAN_Msg_Pend(u8 fifox)
{
)return CAN1->RF0R&0x03;
)return CAN1->RF1R&0x03;
;
}
参数同上
void CAN_RX_Msg(u8 *ide, u32* id, u8* rtr, u8* len, u8 *data, u8 fifox)
{
*ide = (CAN1->sFIFOMailBox[fifox].RIR & <<)>>;
)
{
*id = CAN1->sFIFOMailBox[fifox].RIR >> ;
}
else
{
*id = CAN1->sFIFOMailBox[fifox].RIR >> ;
}
*rtr = (CAN1->sFIFOMailBox[fifox].RIR & <<)>>;
*len = CAN1->sFIFOMailBox[fifox].RDTR & 0x0f;
//接收数据
data[]=CAN1->sFIFOMailBox[fifox].RDLR&0XFF;
data[]=(CAN1->sFIFOMailBox[fifox].RDLR>>)&0XFF;
data[]=(CAN1->sFIFOMailBox[fifox].RDLR>>)&0XFF;
data[]=(CAN1->sFIFOMailBox[fifox].RDLR>>)&0XFF;
data[]=CAN1->sFIFOMailBox[fifox].RDHR&0XFF;
data[]=(CAN1->sFIFOMailBox[fifox].RDHR>>)&0XFF;
data[]=(CAN1->sFIFOMailBox[fifox].RDHR>>)&0XFF;
data[]=(CAN1->sFIFOMailBox[fifox].RDHR>>)&0XFF;
)CAN1->RF0R|=0X20;//释放FIFO0邮箱
)CAN1->RF1R|=0X20;//释放FIFO1邮箱
}
//
u8 CAN_Send_Msg(u8* data, u8 len)
{
u8 mbox;
u16 i = ;
mbox = CAN_TX_Msg(,,len,data);
) && (i < 0xfff)) i++;
;
}
//返回0 接收失败
u8 CAN_Receive_Msg(u8* data)
{
u32 id;
u8 ide = ,rtr = ,len = ;
));
CAN_RX_Msg(&ide,&id,&rtr,&len,data,);
|| rtr!=) ;
else return len;
}
重学STM32---(十) ——CAN通信(二)的更多相关文章
- 重学STM32---(十)之CAN通信(二)
目录 前言 程序编写 主代码 测试 前言 CAN协议是非常难的,但是在stm32中却是简单的,只需要我们配置寄存器即可,,,即使这样,我在学习的时候也遇到了许多困难 程序编写 1.开时钟,不用说 ...
- 从头开始学JavaScript (十二)——Array类型
原文:从头开始学JavaScript (十二)--Array类型 一.数组的创建 注:ECMAscript数组的每一项都可以保存任何类型的数据 1.1Array构造函数 var colors = ne ...
- MINA、Netty、Twisted一起学(十二):HTTPS
由于HTTPS协议是由HTTP协议加上SSL/TLS协议组合而成,在阅读本文前可以先阅读一下HTTP服务器和SSL/TLS两篇博文,本文中的代码也是由这两篇博文中的代码组合而成. HTTPS介绍 上一 ...
- 第十六届“二十一世纪的计算”学术研讨会 牛津大学肿瘤成像学教授Michael Brady主题演讲
Computing and Healthcare 牛津大学肿瘤成像学教授Michael Brady主题演讲" title="第十六届"二十一世纪的计算"学术研讨 ...
- 12天,这本《重学Java设计模式》PDF书籍下载量9k,新增粉丝1400人,Github上全球推荐榜!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言
- 重学 Java 设计模式:实战适配器模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 擦屁屁纸80%的面积都是保护手的! 工作到3年左右很大一部分程序员都想提升自己的技术 ...
- 重学 Java 设计模式:实战外观模式「基于SpringBoot开发门面模式中间件,统一控制接口白名单场景」
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 你感受到的容易,一定有人为你承担不容易 这句话更像是描述生活的,许许多多的磕磕绊绊总 ...
- 重学 Java 设计模式:实战享元模式「基于Redis秒杀,提供活动与库存信息查询场景」
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 程序员的上下文是什么? 很多时候一大部分编程开发的人员都只是关注于功能的实现,只 ...
- Java集合类简单总结(重学)
java集合类简介(重学) 一.Collection(集合).Map接口两者应该是平行关系吧. 1.Map介绍 Map是以键值(key-value)对来存放的,2个值.通过key来找到value(例: ...
随机推荐
- Kids and Prizes(SGU 495)
495. Kids and Prizes Time limit per test: 0.25 second(s)Memory limit: 262144 kilobytes input: standa ...
- JVM调优(这里主要是针对优化基于分布式Mahout的推荐引擎)
优化推荐系统的JVM关键参数 -Xmx 设定Java允许使用的最大堆空间.例如-Xmx512m表示堆空间上限为512MB -server 现代JVM有两个重要标志:-client和-server,分别 ...
- 关于PATH_INFO SCRIPT_NAME SCRIPT_FILENAME REDIRECT_URL 详解
参考:http://www.nginx.cn/426.html http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/09/13/217507 ...
- ACTIVITI 表结构数据分析
ACTIVITI ACT_RU_EXECUTION 表 这个表是工作流程的核心表,流程的驱动都和合格表有密切的关系. 一般来讲一个流程实例都有一条主线.如果流程为直线流程,那么流程实例在这个表 ...
- 选择最适合你的Linux学习方法
我们知道Linux只是一个内核,现在的Linux操作系统底层都是用这个内核,包括Android手机,所以Linux操作系统其实是将Linux内核与应用软件做一个打包,我们称之为Linux发行版.现在比 ...
- Oracle连接查询内容整理
--内连接--select t.*,b.bumenmc from T_HQ_RYXX t,t_hq_bm b where t.bum = b.bumenbm--select * from t_hq_r ...
- Mondriaan的梦(状态压缩dp)
题目原题可以看POJ2411,大意是给出m*n的矩形,要用2*1的矩形将它铺满(不能讲一个矩形铺在另外一个上面),求方案数,并且只要不是完全相同的就算不同的方案,也就是对称算不同的方案. F[i][s ...
- C# Inject
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Di ...
- Android-LogCat日志工具(一)
LogCat : Android中一个命令行工具,可以用于得到程序的log信息. 就像你知道一个人的日志.航程,你可以无时无刻知道一个人在干什么. 而LogCat , 就是程序的日志.通过日志,你可以 ...
- 《Head First设计模式(中文版)》
<Head First设计模式(中文版)>共有14章,每章都介绍了几个设计模式,完整地涵盖了四人组版本全部23个设计模式.前言先介绍<Head First设计模式(中文版)>的 ...