第5章CAN节点应用程序设计本章导读应用程序(eg.MCU=P89V51)CAN收发器eg.CTM8251CAN控制器eg.SJA1000CAN硬件驱动CAN应用层协议驱动功能电路Eg.LED/KEY功能电路驱动CAN节点结构第2章第3章第4章本章本章以前面开发的CAN应用层协议驱动程序为基础,通过一个CAN节点应用程序设计的实例,来展示应用层协议在CAN节点上的具体应用。功能电路驱动蜂鸣器驱动电路按键输入电路LED灯显示电路蜂鸣器驱动按键驱动LED驱动蜂鸣器驱动目的:驱动蜂鸣器发出声音。无源蜂鸣器:如何发声?方法:使无源蜂鸣器不断振荡发出声音。发声时间由发声频率决定T定时时间定时时间到,电平取反取反次数=发声时间×发声频率程序实现程序实现:通过MCU的定时器中断来控制振荡频率。蜂鸣器驱动程序四个函数来实现:voidbuzzerInit(void){……}voidbuzzerQuiet(void){……}voidISR_Timer1(void)interruptTF1_VECTOR{……}voidbuzzerSound(unsignedintuiFreq,unsignedintuiTime){……}//控制蜂鸣器不发声//Timer中断服务函数//Buzzer初始化//发出指定频率的声音蜂鸣器驱动程序四个函数来实现:voidbuzzerQuiet(void){……}voidISR_Timer1(void)interruptTF1_VECTOR{……}voidbuzzerInit(void){……}voidbuzzerSound(unsignedintuiFreq,unsignedintuiTime){……}//控制蜂鸣器不发声//Timer中断服务函数//Buzzer初始化//发出指定频率的声音voidbuzzerInit(void){BuzzCnt=0;TR1=0;//关闭定时器1TF1=0;//清除定时器1中断标志TMOD&=~T0_MASK;//清除旧设置(#defineT0_MASK0x0F)TMOD|=0x01;//设置新模式:16位定时模式BUZZ=1;//置高蜂鸣器控制引脚为高电平ET1=1;//使能定时器中断1EA=1;//设置中断允许}//Buzzer初始化蜂鸣器驱动程序四个函数来实现:voidbuzzerQuiet(void){TR1=0;//关闭定时器1TF1=0;//清除定时器中断标志BUZZ=1;//置高蜂鸣器的控制引脚电平}//控制蜂鸣器不发声蜂鸣器驱动程序四个函数来实现:voidISR_Timer1(void)interruptTF1_VECTOR{if(BuzzCnt){//允许蜂鸣器发声TR1=0;//关闭定时器1TL1=TL1_Load;//设置定时器的计数值低8位TH1=TH1_Load;//设置定时器的计数值高8位TR1=1;//启动定时器BUZZ=!BUZZ;//蜂鸣器控制电平取反BuzzCnt--;//蜂鸣器响的次数减1}else{buzzerQuiet();//关闭定时器,在蜂鸣器震荡次数为0时}}//Timer中断服务函数蜂鸣器驱动程序四个函数来实现:voidbuzzerSound(unsignedintuiFreq,unsignedintuiTime){if(uiFreq20){buzzerQuiet();return;}if(uiFreq20000)uiFreq=20000;TL1_Load=LOW_BYTE(65536UL-CPUCLK/(uiFreq*2));TH1_Load=HIGH_BYTE(65536UL-CPUCLK/(uiFreq*2));BuzzCnt=uiFreq;BuzzCnt*=uiTime;BuzzCnt/=500;TL1=0xF0;TH1=0xFF;TR1=1;}//发出指定频率的声音//限定频率范围在20~20000Hz之间20Hz20KHz次声超声人耳能识别的范围//计算Timer0装载值//根据发声时间设置取反次数//启动Timer发声时间由发声频率决定T定时时间定时时间到,电平取反发声次数=发声时间×发声频率取反次数=发声次数×2=发声时间×发声频率×2=uiTime(ms)×10-3×uiFreq×2发声频率发声时间按键驱动目的:获取按键的状态。方法:读取与按键相连的MCU引脚的值。按键按下,P3.2=0;按键释放,P3.2=1按键驱动程序程序实现:#defineKEY1P3_2//定义按键和mcu的连接关系staticcharoldKey;voidkeyInit(void){oldKey=KEY1;//设置按键的初始检测电平}charkeyGet(char*key){if(KEY1!=oldKey){//按键状态发生改变oldKey=KEY1;//设置oldKey的值if(KEY1){*key=0;//按键释放}else{*key=1;//按键按下}return1;//按键有动作返回1}return0;//按键没有动作}//按键初始化//获取按键状态按键按下,P3.2=0,*key设置为1按键释放,P3.2=1,*key设置为0LED驱动目的:点亮或熄灭LED。方法:直接控制与LED相连的MCU引脚。P1.0=1,D1点亮P1.0=0,D1熄灭LED驱动程序程序实现:#defineD1P1_0voidledInit(void){D1=0;//熄灭D1}voidledSet(unsignedcharval){if(val){D1=1;//点亮D1}else{D1=0;//熄灭D1}}//LED初始化//LED灯控制函数,val是LED的控制参数应用程序-设计思想目的:展示CAN应用层协议在CAN节点上的具体应用。方法:通过调用各个驱动程序来对不同外设进行控制完成各种需要的功能。初始化开始接收到CAN报文?处理CAN报文按键状态发生改变?发送CAN报文YNY流程图:字段描述ID.10~ID.7发送CAN报文节点的地址(SrcAddr)ID.6~ID.3接收CAN报文节点的地址(DstAddr)ID.2~ID.0功能码(FunCode),指明一帧数据的作用FunDataLen功能参数长度变量FunData功能参数数组,最多包含8字节表4.1自定义应用层协议说明N应用程序-实现功能节点0节点1将两个CAN节点的地址设为互补按键按下发送CAN帧接收CAN帧点亮LED发送CAN帧接收CAN帧蜂鸣按键释放发送CAN帧接收CAN帧熄灭LED发送CAN帧接收CAN帧蜂鸣同样,节点2按键状态发生改变时,现象相同。功能码功能参数地址设为0地址设为1