can总线 单片机 我是单片机初学者,有51单片机和pic单片机编程基础,现在想学学can总线技术。

can总线 单片机 我是单片机初学者,有51单片机和pic单片机编程基础,现在想学学can总线技术。,第1张

#include <at89x51.h>

#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我


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/8106191.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-13
下一篇 2023-04-13

发表评论

登录后才能评论

评论列表(0条)

保存