#include "SJA1000_PELI.h"
sfr WDT_CONTR = 0xe1 //STC单片机的看门狗所用寄存器
//*******************************************************
//按键与LED灯定义
//*******************************************************
#define LED0 P1_0
#define LED1 P1_1
#define LED2 P1_2
#define LED3 P1_3
#define KEY0 P1_4
#define KEY1 P1_5
#define KEY2 P1_6
#define KEY3 P1_7
//*******************************************************
//引用的外部变量声明
//*******************************************************
extern bit g_RiFlag //CAN总线接收全局标志位声明
extern unsigned char TX[11] //发送临时缓冲区声明
extern unsigned char RX[11] //接收临时缓冲区声明
//*******************************************************
//引用的外部函数声明
//*******************************************************
extern void SJAInit(void) //SJA1000初始化函数声明
extern bit SJASendData(unsigned char *SendDataBuf) //SJA1000低层发送函数声明
extern bit SJAReceData(unsigned char *ReceiveDataBuf)//SJA1000低层接收函数声明
//*******************************************************
//全局变量声明
//*******************************************************
unsigned char code LEDstyle[4][11] = { {0x08,0xff,0xff,0xfe,0xfd,0xfb,0xf7,0xf7,0xfb,0xfd,0xfe},
{0x08,0xff,0xff,0xf9,0xf6,0xf9,0xf6,0xf9,0xf6,0xf9,0xf6},
{0x08,0xff,0xff,0xf1,0xf2,0xf4,0xf8,0xf1,0xf2,0xf4,0xf8},
{0x08,0xff,0xff,0xfc,0xf9,0xf3,0xf6,0xfc,0xf9,0xf3,0xf6}
}
//帧类型及长度,帧ID高8位,帧ID低3位,一帧中0-8个字节数据
//*******************************************************
//函数声明
//*******************************************************
void RS232Init(void) //串口初始化函数声明
void RS232Send(unsigned char tempdata) //串口发送函数声明
void DelayTime (unsigned char times) //延时函数声明
void CANSend(unsigned char style) //CAN总线发送函数声明
void CANRece(void) //CAN总线接收函数声明
//*******************************************************
//主函数
//*******************************************************
void main(void)
{
P1 = 0xff
RS232Init() //串口初始化,19200,1停止位,没校验
SJAInit() //SJA初始化
//WDT_CONTR = 0x3c //STC单片机的看门狗,喂狗
EA = 1
while(1)
{
if (KEY0 ==0) { while (!KEY0)CANSend(0)} //KEY0按下,则发送流水灯花式0
if (KEY1 ==0) { while (!KEY1)CANSend(1)} //KEY1按下,则发送流水灯花式1
if (KEY2 ==0) { while (!KEY2)CANSend(2)} //KEY2按下,则发送流水灯花式2
if (KEY3 ==0) { while (!KEY3)CANSend(3)} //KEY3按下,则发送流水灯花式3
if (g_RiFlag) { g_RiFlag = 0CANRece()} //全局中断标志位如为1,则接收并处理
//WDT_CONTR = 0x3c //STC单片机的喂狗,用S5X不用加此句
}
} //主程序结束
///******************************************************
//CAN发送处理函数
///******************************************************
void CANSend(unsigned char style)
{
TX[0] = LEDstyle[style][0]
TX[1] = LEDstyle[style][1]
TX[2] = LEDstyle[style][2]
TX[3] = LEDstyle[style][3]
TX[4] = LEDstyle[style][4]
TX[5] = LEDstyle[style][5]
TX[6] = LEDstyle[style][6]
TX[7] = LEDstyle[style][7]
TX[8] = LEDstyle[style][8]
TX[9] = LEDstyle[style][9]
TX[10] = LEDstyle[style][10]
SJASendData(TX) //将要发送的数据放到SJA1000的发送缓冲区
SJARegWrite(0x01, 0x10) //启动自发自收
}
//*******************************************************
//CAN接收处理函数
//*******************************************************
void CANRece(void)
{
unsigned char i
unsigned char tempdata
for (i=0i<8i++) //用四个LED循环显示接收到的八个数据(每个数据只用低四位)
{
tempdata = RX[i+3] //循环读取SJA1000接收缓冲区里的8个数据字节
RS232Send(tempdata) //并将值发送到串口,可通过串口软件监控数据
tempdata |= 0xf0 //为了不改变键盘数值,加此句
P1 =tempdata //送到LED灯显示
DelayTime(1000) //延时,让流水灯的花式可以观察得到
}
P1 = 0xff //清除所有显示
}
//*******************************************************
//串口初始化
//*******************************************************
void RS232Init(void)
{
SCON = 0x50//SCON: 串口工作方式1, 8位数据位,1位停止位
TMOD |= 0x20//TMOD: 定时器1, 工作方式2, 8位自动重载
PCON |= 0x80//SMOD=1
TH1 = 0xFD//SMOD=1,波特率:19200 晶振=11.0592MHz
//IE |= 0x90 //使能串口中断
TR1 = 1 //启动定时器1
}
//*******************************************************
//串口发送函数
//*******************************************************
void RS232Send(unsigned char tempdata)
{
SBUF =tempdata //在显示的同时,也把数据往串口发送
while(!TI)
TI = 0
}
//*******************************************************
//延时函数
//*******************************************************
void DelayTime (unsigned char times)
{
unsigned char i=0
while(times--)
{
for(i=0i<50i++)
{}
}
}
//*******************************************************
//结束
//*******************************************************
首先,要明确你要的应答是什么,是正确接收某个报文,还是某个节点向另一节点请求报文一、正确接收报文:
CAN报文包含一个ID场的部分,每个报文在总线上广播,节点收到报文后比较ID,如果是该节点应该接受的报文ID,该节点则完成接受;
二、请求报文:
CAN报文内在ID场前有一个1bit长度远程帧场,0表示为普通帧,1表示为远程帧,当A节点希望B节点向它发送某个报文时,A节点向总线广播远程帧,远程帧无数据场,总线上节点同样也是比较报文的ID场,当B节点比对ID场发现该远程帧是向它请求时,B节点发送该远程帧请求的帧,A通过第一点中的方法接受收
PS:CAN总线报文的CRC校验场后面会有一个ACK应答场,发送报文的节点发出的ACK(1Bit)为“1”,正确应答的节点(报文数据校验通过正确)会将总线上的这个ACK位电平拉成“0”,表示正确应答。
若A节点广播报文后,发现该报文的ACK始终为“1”,则其收发器将从缓存中自动重发该帧,直到有节点正确接受ACK为“0”或者A节点离线
希望对你有帮助,还有不完整或不理解的可以追加提问或者M我
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)