本帖最后由 woriaty 于 2015-10-27 21:05 编辑
在上篇整体规划中已经介绍了车联网项目的基本结构,下面介绍第一部分功能,即CAN总线数据接收并转换为串口数据的实现方法:
1、硬件架构
CAN总线接收采用带CAN通讯模块的飞思卡尔
单片机MC9S12XS128实现,在接收时采用PCA82C251芯片作为CAN协议控制器和物理总线的接口,下图是自己做的带CAN总线收发器的飞思卡尔单片机最小系统:
背面是PCA82C251芯片(纯手工焊接,不是很美观,哈哈^_^):
2、软件架构
通过对飞思卡尔单片机寄存器配置实现单片机中断接收CAN总线数据的功能,具体配置代码如下:
- /* 初始化CAN0 */
- void INIT_CAN0(void)
- {
- if(CAN0CTL0_INITRQ==0) // 查询是否进入初始化状态
- CAN0CTL0_INITRQ =1; // 进入初始化状态
- while (CAN0CTL1_INITAK==0); //等待进入初始化状态
- CAN0BTR0_SJW = 0; //设置同步
- CAN0BTR0_BRP = 7; //设置波特率
- CAN0BTR1 = 0x1c; //设置时段1和时段2的Tq个数 ,总线频率为250kb/s
- // 关闭滤波器
- CAN0IDMR0 = 0xFF;
- CAN0IDMR1 = 0xFF;
- CAN0IDMR2 = 0xFF;
- CAN0IDMR3 = 0xFF;
- CAN0IDMR4 = 0xFF;
- CAN0IDMR5 = 0xFF;
- CAN0IDMR6 = 0xFF;
- CAN0IDMR7 = 0xFF;
- CAN0CTL1 = 0xC0; //使能MSCAN模块,设置为一般运行模式、使用总线时钟源
- CAN0CTL0 = 0x00; //返回一般模式运行
- while(CAN0CTL1_INITAK); //等待回到一般运行模式
- while(CAN0CTL0_SYNCH==0); //等待总线时钟同步
- CAN0RIER_RXFIE = 1; //使能接收中断
- }
- /* CAN0接收 */
- Bool MSCAN0GetMsg(struct can_msg *msg)
- {
- unsigned char sp;
- // 检测接收标志
- if(!(CAN0RFLG_RXF))
- return(FALSE);
-
- // 检测 CAN协议报文模式 (一般/扩展) 标识符
- if(CAN0RXIDR1_IDE)
- // IDE = Recessive (Extended Mode)
- return(FALSE);
- // 读标识符
- msg->id = (unsigned int)(CAN0RXIDR0<<3) |
- (unsigned char)(CAN0RXIDR1>>5);
-
- if(CAN0RXIDR1&0x10)
- msg->RTR = TRUE;
- else
- msg->RTR = FALSE;
-
- // 读取数据长度
- msg->len = CAN0RXDLR;
-
- // 读取数据
- for(sp = 0; sp < msg->len; sp++)
- msg->data[sp] = *((&CAN0RXDSR0)+sp);
- // 清 RXF 标志位 (缓冲器准备接收)
- CAN0RFLG = 0x01;
- return(TRUE);
- }
在接受CAN总线数据时需要知道节点ID才能接受对应节点的数据,刚好公司现在在做新能源汽车变速箱实验,因此得到了变速箱控制器CAN总线节点ID,读取的CAN报文内容即为变速箱控制器共享至CAN总线网络中的档位、电机转速和电池电压数据,后面可以根据电机转速计算出对应的车速。
接收到数据后使用SCI将其转化为串口数据发送,SCI配置如下:
- /* 串口通信 */
- /* 初始化SCI */
- void INIT_SCI(void)
- {
- SCI0BD = BUS_CLOCK/16/BAUD; //设置SCI0波特率为9600
- SCI0CR1 = 0x00; //设置SCI0为正常模式,八位数据位,无奇偶校验
- SCI0CR2 = 0x08; //允许发送数据
- }
- /* 串口发送函数 */
- void SCI_send(unsigned char data)
- {
- while(!SCI0SR1_TDRE); //等待发送数据寄存器(缓冲器)为空
- SCI0DRL = data;
- }
- /* 串口发送数据函数 */
- void send_string(unsigned char *putchar)
- {
- unsigned char i;
- for(i=0;i<8;i++)
- SCI_send(*putchar++);
- }
- /* 内容填写 */
- void String_Init(void)
- {
- putstring[0]=0xaa; //头校验文件
- putstring[1]=Speed/256; //转速信号拆分
- putstring[2]=Speed%256; //转速信号拆分
- putstring[3]=D; //档位
- putstring[4]=Volt; //电池电压
- putstring[5]=0x55; //尾校验文件
- }
以上便实现了新能源汽车CAN总线数据读取和将其转化为SCI数据发送的功能。