#1楼主:[转载]CAN总线学习笔记二:CAN自收发程序解读
文章发表于:2008-06-17 05:23
在浏览各个blog的时候,突然发现ilove314写的一篇针对我们can学习板学习的笔记,觉得写的很不错,相信能给很多人以启迪,这里我把这篇文章转载过来,大家可以一起参考一下。和ilove314也交流过,觉得学习还是很主动的,把自己学习的体会写出来,对自己也是一个提高的过程。
最近看到有一些人问关于程序的内容,其实有的东西是靠你自己去琢磨的,比如看看ilove314写的,就会感觉,从硬件与软件两方面结合起来,就会明白程序为什么这么写。而且有的时候,觉得那句话是不是有用的时候,可以删去了,注释掉了,自己去试一试才会明白到底是怎么回事。给大家CAN的程序也是我们从实际的项目中进行精简和简化过的,所以可能会有一些地方你会有疑问,但是不要紧,关键是你能通过借鉴这个程序,来移植到你自己的项目中并跑起来,对吧?
好了,最后再次感谢ilove314的文章,希望他写出更好的学习心得!也希望大家能写出与此相当的文章!
我计划,等这次活动之后,将所有的资料整理成一个大的文档,同时会收录一些网友写的不错的文章,被收录文章的作者将会收到我们设计的NRF2401无线pcb或者是USB转串口pcb最为奖励。希望大家能把你写的与EDN-CAN开发板相关的学习心得发到我们的小组里,这样我们才能看到,大家也能收集到,最后搞个小小的投票,来选出最好的文章。
CAN总线学习笔记二:CAN自收发程序解读
花了一整个下午的时间,彻头彻尾的把 PIAE小组提供的CAN自收发源程序解读了一遍。解读别人的程序是一件挺费时费力的一件事,但是在对某项技术或者说某个芯片的入门阶段参考别人的程序又是一项必不可少的任务。
对于这个程序,头一个任务当然是把头文件先浏览一遍,能弄明白的还是先弄明白,对后面程序的解读有好处。C文件里给出了三个头文件:
#include
#include
#include
第一个reg52.h我就不废话了,下一个intrins.h我在上一篇日志里也详细的作了说明,这里也不提了。can_selfdef.h是程序员自己定义的一个头文件,在这个头文件里除了一些宏定义和管脚的一些说明外,最重要的就是要弄明白“CAN总线SJA1000寄存器地址定义”。这个我开始也没弄明白,后来反复琢磨,才发现作者在这个程序里吧SJA1000的寄存器作为单片机的外部扩展RAM寻址了,从而省去了编写一些底层的驱动程序,这就让大家连SJA1000的datasheet的时序图都不用看了(不过下一步我想用驱动程序来控制SJA1000)。
看完头文件,可不能从第一个程序依次往下看。应该直接找到主程序main()解读:
void main(void)
{
//MCU初始化(主要是各中断寄存器的初始化)
SJA_RST = 1; //CAN总线复位管脚复位无效
SJA_CS = 0; //CAN总线片选有效
EX1 = 1; //开MCU外部中断INT1
IT1 = 0; //MCU外部中断INT1为电平触发,也是CAN总线接收中断口
IT0 = 1; //MCU外部中断INT0为下降沿触发
EX0 = 1; //开MCU外部中断INT0
EA = 1; //开MCU总中断
SJA_CS = 1; //CAN总线片选无效,使得对数据总线的操作不会影响SJA1000。
//SJA1000初始化
CAN_init(); //对SJA1000寄存器的读写是采用外部寄存器寻址方式,
//所以不需要程序单独控制片选有效无效
_nop_();
_nop_();
//主循环
while(1)
{
_nop_();
_nop_();
Rxd_deal(); //接收处理程序
Txd_deal(); //发送处理程序
led_seg7(0,Txd_data); //数码管1-2显示发送数据子程序
led_seg7(1,Rxd_data+3); //数码管3-4显示接收数据子程序
}
}
上面的注释是本人详细做了加工的,先是单片机中断寄存器的初始化,打开了单片机的INT0和INT1两个外部中断。INT0是外接按键的,所以是下降沿触发。这个按键每按下一次,待发送的数据的第一个字节就会加一,这个数据同时会显示在数码管上。而INT1是外界着SJA1000的发送数据中断端口的,采用电平触发,也就是说当SJA1000发送数据时,就会触发中端口INT1,从而让单片机进行数据的接收工作。
接下来是SJA1000的各个寄存器的初始化,主要是在CAN_init();这个程序里完成的,主要是设置一些寄存器使得满足本次试验的要求。
最后就进入了主循环中。不断的进行接收数据处理、发送数据处理以及将数据的头一个字节的数值显示在数码管上。每当按键被按下后就会置位发送数据状态标志位,这时就进入发送状态,无非就是把ID码和数据等13个字节送入SJA1000的相应寄存器里,其它的事情就交给SJA1000