重学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(例: ...
随机推荐
- Tengine vs openresty
简介 Tengine是由淘宝网发起的Web服务器项目.它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性.Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到 ...
- json小例子
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8 ...
- JDE报表开发笔记(Client端导出Excel乱码)
之前导出Excel时没发生任何问题, Client端PL/SQL字符集为UTF-8 Oracle JDE E910字符集为UTF-8 解决方式:添加指定用户的字符集(上图即为修改后的用户字符集) 角色 ...
- js在mootools框架下的new Class
首先,在HTML文件中引入mootools.js. mootools-more.js.mootools-core.js,然后就能使用mootools封装的一些特性. 几乎类似于面向对象. mootoo ...
- RHEL 5 安装phpqrcode生成二维码
VMWARE中全新安装(默认)RHEL. 之后,yum 安装备apache/php 下载并上传phpqrcode 1.1.4版本,并将其解压至/var/www/html/phpqrcode (去掉ip ...
- javascrip自定义对象的方式
对象初始化方式(也叫json对象创建方式) <script type="text/javascript"> var User = { name:"paul&q ...
- python操作二进制文件
有的时候需要用python处理二进制数据,比如,存取文件,socket操作时.这时候,可以使用python的struct模块来完成.可以用 struct来处理c语言中的结构体. struct模块中最重 ...
- IP数据报的格式
1. IP数据报首部的固定部分中的各字段 ①版本:占4位,指IP协议的版本.通信双方使用的 IP协议版本必须一致.日前广泛使用的 IP协议版本号为 4 (即 IPv4). IPv6 目前还处于起步阶段 ...
- struts2的返回类型
return 一个字符串,如果是success 直接 服务器端跳转 返回到和方法名对应的页面去 不过如果返回的页面和方法没有太大关系,比如删除修改添加之后要 客户端跳转 返回所有用户列表,这个时候可以 ...
- cometd的服务器配置
CometDServlet必须在web.xml中进行配置,如下: <servlet> <servlet-name>cometd</servlet-name& ...