您的位置 首页 知识

根据单片机的CAN总线通讯程序

——————————————————CAN==>UART的协议转换器程序名称:CAN—>UART协议转换程序透

//——————————————————

//CAN <==> UART的协议转化器
//
//程序称号:CAN <---> UART协议转化程序<通明方法>
//
//作者:王猛
//创立:2007-10-09
//
//阐明:
//1,单片机运用P89C61X2BA
//–晶振11.0592MHZ
//–CAN总线中止运用单片机的中止0,外部有上拉电阻,波特率能够设定
//2,CAN总线发送选用查询方法,接纳选用中止方法
//3,看门狗复位时刻1.2S
//4,SJA1000晶振8MHZ,Peil形式
//5,串口中止接纳,查询发送,波特率可设置
//6,×××当串口收到数据后,每8个数一组打包,经过CAN总线发送出去
//
//—–10.16日,从头修正程序完结以下功用—–
//—-此功用现已改为,每收到一帧数据,发动一次CAN传输,传输字节数等于串口收到的数据
//—-串行帧的帧间界定经过当时波特率下传输5个字节为时刻距离,详细为当次序接纳到的任
//意两个数据,它们之间的时刻距离大于5个字节传送时刻,以为这两个数据分归于两个不
//同的帧
//
//7,当CAN总线每接纳一帧信息后,经过串口发送出去
//—–10.15日,改为能够辨认CAN的报文字节长度,即串口只发送CAN报文长度个字节
//8,看门狗芯片MAX1232CPA,硬件溢出时刻1.2S
//
//——————————————————-

#include
#include
#include#include “CANCOM.h”

//unsigned char UART_TX_Data[8] = {0,1,2,3,4,5,6,7};
//unsigned char CAN_TX_Data[8] = {0,1,2,3,4,5,6,7};
unsigned char xdata UART_RX_Data[255];//串口接纳到的串行帧
unsigned char xdata CAN_TX_Data[255];//待发送的数据缓冲区
unsigned char code ACR_ID[4] = {0,0,0,0};//CAN初始设置检验滤波值
unsigned char code AMR_ID[4] = {0xff,0xff,0xff,0xff};
unsigned char CAN_TX_ID[4] = {0,0,0,0};//待发送的方针的ID
unsigned char CAN_RX_ID[4] = {0,0,0,0};//接纳到的信息来自何ID
unsigned char CAN_RX_Data[8] = {7,6,5,4,3,2,1,0};//承受到的数据缓冲
unsigned char code CAN_BTR0[10] = {0xdf,0xcf,0xc7,0xc3,0x43,0xc1,0xc1,0xc0,0xc0,0x80};
unsigned char code CAN_BTR1[10] = {0x7f,0x7f,0x7f,0x7f,0x2f,0x7f,0x4d,0x3e,0x3a,0x23};
//5K 10K 20K 40K 50K 80K 100K 200K 250K 500K
unsigned char code UART_BTR[4] = {0xe8,0xf4,0xfa};
// 1.2K,2.4K,4.8K

unsigned char CAN_flag;//CAN发送标志位
unsigned char UART_flag;//
unsigned char CAN_ERROR_flag = NOT;//
unsigned char CAN_DataLength = 8;//CAN信息的报文长度
unsigned char UART_DataLength = 0;//串口接纳时的当时指示
unsigned char UART_Length = 0;//串口接纳区的长度指示
//sbit AAA = P1^4;

void main(void)
{
EA = 0;
System_init();//体系初始化
Timer_init();//守时器初始化
Interrupt_init();//中止
UART_ini();
CAN_init();
Delay(1);
W_WDT();
EA = 1;

//Delay(1);
//UART_Length = 8;
//CAN_Transmit(0);
//UART_Transmit();

while (1)
{
W_WDT();

if (CAN_flag == YES)
{
CAN_flag = NOT;
CAN_Transmit(0);
LED1 = !LED1;
}
else
{
CAN_flag = NOT;
}
/*
if (UART_flag == YES)
{
UART_flag = NOT;
//Delay(50);
UART_Transmit();
//Clear_Buffer(CAN_RX_Data,8);
//LED3 = !LED3;
}
else
{
UART_flag = NOT;
}

*/
if ((CAN_ERROR_flag == YES))
{
CAN_ERROR_flag = NOT;
CAN_init();
}
else
{
CAN_ERROR_flag = NOT;
}
}
}
//—————————
//功用:体系设置
//–外部数据存储区拜访使能
//–LED指示灯关(1=on,0=off)
//–流程操控标志置为无效NOT
//–清空串口,CAN的相关数据缓冲区
//—————————
void System_init(void)
{
CKCON = 0x00;//Fosc devide 12
AUXR = 0x00;//0x02;//EXM enable
LED1 = 0;//LED0-3 off指示灯,共阴接法,1时亮
LED2 = 0;
LED3 = 0;
LED4 = 0;
WDT = 1;//WDT ini

CAN_DataLength = 8;
UART_DataLength = 0;
UART_Length = 0;

CAN_flag = NOT;
CAN_ERROR_flag = NOT;
//UART_flag = NOT;

Clear_Buffer(UART_RX_Data,255);
Clear_Buffer(CAN_TX_Data,255);
Clear_Buffer(CAN_TX_ID,4);
Clear_Buffer(CAN_RX_ID,4);
Clear_Buffer(CAN_RX_Data,8);

/*
CAN_flag = YES;
UART_flag = YES;
*/
}
//—————————–
//
//软件延时(非准确)
//—-内置清看门狗守时器子函数
//避免屡次调用延时过长导致
//看门狗复位
//
//—————————–
void Delay(unsigned char time)
{
unsigned char i;
unsigned int j;

for (i = 0;i < time;i++)
{
W_WDT();
for (j=0;j<30000;j++)
{
}
}
}

//———————————
//串行口初始化设置
//方法1,8数据位,一个中止位,无奇偶校验
//串口中止答应
//————————————
void UART_ini(void)
{
SCON = 0x50;//方法1,波特率可变,8bits,承受答应
PCON&= 0x7F;//SMOD = 0
TMOD |= 0x20;//timer1 mode 2

TL1 = UART_BTR[2];//|f
//|波特率=———————-
TH1 = UART_BTR[2];//|32*2^smod*12*(256-TL1)
TCON |= 0x40;//start

TI = 0;
}

//———————————————–
//
//看门狗“喂狗”程序,WDT的一个下降沿触发一次
//
//———————————————–
void W_WDT(void)//triggle WDT
{
unsigned char i;
WDT = 1;
for (i=0;i<10;i++)
{
}
WDT = 0;
}

//—————————————————
//
//中止初始化
//
//—-外部中止0有用,下降沿触发,用于SJA1000发生CAN事情中止
//—-守时器中止,用于断定串口接纳的次序两个字节是否分属两帧
//—-串口中止,RX运用中止,TX未运用
//—-中止优先级暂时未设定
//
//—————————————————
void Interrupt_init(void)
{
//IP = 0x00;
IT0 = 0x01; //外部0中止沿触发

ET0 = 1;//守时器0中止使能
EX0 = 1;//外部中止使能
ES = 1; //串行中止使能
}

//—————————————————
//
//守时中止程序
//
//一旦中止,阐明一帧的接纳现已结束,开端发动CAN发送程序
//把串口接纳到的数据准备好给CAN总线发送
//RX_buffer ===> CAN_TX_buffer
//
//—————————————————
void Timer0_ISR(void) interrupt 1 using 2
{
static unsigned char i;
//unsigned char counter;

//TH0 = temp_TH0;
//TL0 = temp_TL0;

/*counter += 1;
if (counter == 20)//到1S了么?
{
//UART_flag = YES;
}
if (counter == 40)//到2S了么?
{
//CAN_flag = YES;
counter = 0;
}*/
//AAA = !AAA;
TR0 = 0;//守时器关,开端次CAN信息传送

for (i=0;i<uart_datalength;i++)
{
CAN_TX_Data[i] = UART_RX_Data[i];
}
UART_Length = UART_DataLength;
UART_DataLength = 0;
CAN_flag = YES;
}
//—————————————————————
//
//串口中止服务程序
//
//—-只要接纳运用
//—-每收一个数从头初始化守时器
//
//—————————————————————-
void RX_INT(void) interrupt 4 using 3
{
static unsigned char n;

if (RI==1)
{
do
{
RI = 0;
}
while (RI != 0);

//UART_RX_Data[UART_DataLength++] = SBUF;
n = SBUF;
UART_Send_Byte(n);

TH0 = temp_TH0;
TL0 = temp_TL0;
TR0 = 1;//发动数据距离守时,判别是否分属两帧
}
else
{
//TX
}
}
//—————————————————————
//
//串口发送单字节程序
//
//—————————————————————-
void UART_Send_Byte(unsigned char Data)
{
SBUF = Data;
while (TI == 0)//等候发送结束
{
}
TI = 0;
}

//—————————————————————
//
//初始化守时器程序
//
//—-守时器0方法1,守时器1方法2留给串口
//
//—————————————————————-
void Timer_init(void)
{
TMOD |= 0x01;//运用守时器0-方法1

TH0 = temp_TH0;
TL0 = temp_TL0;
//TR0 = 1;//这儿不翻开守时器
}

void CAN_init(void)
{

EA = 0;
MOD_CAN1 |= 0x08;//单滤波方法
do
{
MOD_CAN1 |= 0x01; //request to reset mode
}
while ((MOD_CAN1&0x01) != 0x01);

CDR_CAN1 = 0xc8;//挑选PeliCAN形式,运用输入比较器,clk_out封闭
IER_CAN1 = 0x01;//答应发送中止,其他中止禁能

ACR0_CAN1 = ACR_ID[0];
ACR1_CAN1 = ACR_ID[1];
ACR2_CAN1 = ACR_ID[2];
ACR3_CAN1 = ACR_ID[3];
AMR0_CAN1 = AMR_ID[0];
AMR1_CAN1 = AMR_ID[1];
AMR2_CAN1 = AMR_ID[2];
AMR3_CAN1 = AMR_ID[3];

//ECC_CAN1 = 0;
//TXERR_CAN1 = 0;
//RBSA_CAN1 = 0;

BTR0_CAN1 = CAN_BTR0[0];
BTR1_CAN1 = CAN_BTR1[0];
OCR_CAN1 = 0xaa;//normal output

W_WDT();
do
{
MOD_CAN1 &= 0xfe;
}
while ((MOD_CAN1&0x01) != 0x00);
EA = 1;
}

//———————————–
//
//串口发送一帧承受到的CAN数据
//
//—-长度1-8,依据接纳到的CAN信息来确认
//
//———————————–
void UART_Transmit(void) //using 0
{
unsigned char i;

LED3 = !LED3;
for (i=0;i{
UART_Send_Byte(CAN_RX_Data[i]);
}
}
//———————————–
//
//CAN发送承受到的一帧串口数据
//
//—-最大长度255,依据接纳到的串口信息的
//个数来确认
//—-按每顺次8个数据作为一个CAN帧的报文部分
//缺乏8个或超越8的倍数的部分按实践个数作
//为CAN报文
//—-FarmeType = 1为扩展帧,FarmeType = 0为
//规范帧
//———————————–
void CAN_Transmit(bit FarmeType)
{

unsigned char i;
unsigned char m;
unsigned char can_status;
unsigned char xdata *pointer;

if (FarmeType == 0)//规范帧
{
for (m=0;m<(UART_Length/8);m++)
{
W_WDT();
do//发送缓冲区空么?
{
can_status = SR_CAN1;
}
while ((can_status&0x04) != 0x04);

TXFrameInfo1 = 0x00 + 0x08;
pointer = &TXID1;
for (i=0;i<2;i++)
{
*(pointer++) = CAN_TX_ID[i];
}

pointer = &TXID3;
for (i=0;i<8;i++)
{
*(pointer++) = CAN_TX_Data[i+8*m];
}
CMR_CAN1 = Request_TX;
W_WDT();
}

if ((UART_Length%8) != 0)
{
W_WDT();
do //发送缓冲区空么?
{
can_status = SR_CAN1;
}
while ((can_status&0x04) != 0x04);
TXFrameInfo1 = 0x00 + UART_Length%8;
pointer = &TXID1;
for (i=0;i<2;i++)
{
*(pointer++) = CAN_TX_ID[i];
}

pointer = &TXID3;
for (i=0;i<(UART_Length%8);i++)
{
*(pointer++) = CAN_TX_Data[i+8*(UART_Length/8)];
}
CMR_CAN1 = Request_TX;
W_WDT();
}
else
{
}
}
else//扩展帧
{
for (m=0;m<(UART_Length/8);m++)
{
W_WDT();
do//发送缓冲区空么?
{
can_status = SR_CAN1;
}
while ((can_status&0x04) != 0x04);

TXFrameInfo1 = 0x80 + 0x08;
pointer = &TXID1;
for (i=0;i<4;i++)
{
*(pointer++) = CAN_TX_ID[i];
}

pointer = &TXDATA1;
for (i=0;i<8;i++)
{
*(pointer++) = CAN_TX_Data[i+8*m];
}
CMR_CAN1 = Request_TX;
W_WDT();
}

if ((UART_Length%8) != 0)
{
W_WDT();
do//发送缓冲区空么?
{
can_status = SR_CAN1;
}
while ((can_status&0x04) != 0x04);
TXFrameInfo1 = 0x80 + UART_Length%8;
pointer = &TXID1;
for (i=0;i<4;i++)
{
*(pointer++) = CAN_TX_ID[i];
}

pointer = &TXDATA1;
for (i=0;i<(UART_Length%8);i++)
{
*(pointer++) = CAN_TX_Data[i+8*(UART_Length/8)];
}
CMR_CAN1 = Request_TX;
W_WDT();
}
else
{
}
}

UART_Length = 0;

}

//———————————–
//
//CAN接纳中止服务程序
//
//—-判别是否是RX中止,如果是
//把承受到的CAN信息经过串行口发送出去
//—-其他的中止阐明CAN总线呈现过错或脱离
//
//———————————–
void CAN_ISR(void) interrupt 0 using 1
{
unsigned char can_int;

EA = 0;

can_int = IR_CAN1;
if ((can_int&0x01) == 0x01)//接纳中止
{
CAN_Receive();
CMR_CAN1 |= ReleaseRXBuf;
}
else
{
CAN_ERROR_flag = YES;//其他中止,暂时未用
}

//UART_flag = YES;
//CAN_flag = YES;
UART_Transmit();

EA = 1;
}

//———————————–
//
//CAN接纳数据函数
//
//—-依据承受到的帧信息,按不同的长度存储
//报文数据
//
//———————————–
void CAN_Receive(void) using 1
{
unsigned char i;
unsigned char xdata *pointer;
unsigned char Info;

Info = RXFrameInfo1;

if ((Info&0x80) == 0)//standard Frame
{
//CAN_RX_ID[0] = RXID1;
//CAN_RX_ID[1] = RXID2;

CAN_DataLength = Info&0x0f;
pointer = &RXID3;
for (i=0;i{
CAN_RX_Data[i] = *(pointer++);
}
for (;i<8;i++)
{
CAN_RX_Data[i] = 0x00;
}
}
else//Ex Frame
{
//CAN_RX_ID[0] = RXID1;
//CAN_RX_ID[1] = RXID2;
//CAN_RX_ID[2] = RXID3;
//CAN_RX_ID[3] = RXID4;
CAN_DataLength = Info&0x0f;
pointer = &RXDATA1;
for (i=0;i{
CAN_RX_Data[i] = *(pointer++);
//pointer += 1;
}
for (;i<8;i++)
{
CAN_RX_Data[i] = 0x00;
}
}
}
//———————————–
//
//清0缓冲区
//
//—-pointer,指向待清0 的缓冲区首地址
//—-length 清0 的长度
//———————————–
void Clear_Buffer(unsigned char *pointer,unsigned char length)
{
unsigned char i;

for (i=0;i{
*(pointer++) = 0x00;
}
}

别的头文件为:

#ifndef _CANCOM_H
#define _CANCOM_H

#define CS1_SJA1000 0x7f00//SJA1000 Pin /CS —-> P2.7,low level active

#define MOD_CAN1XBYTE[CS1_SJA1000+0] //Peli
#define CMR_CAN1XBYTE[CS1_SJA1000+1]//command
#define SR_CAN1XBYTE[CS1_SJA1000+2] //state
#define IR_CAN1XBYTE[CS1_SJA1000+3] //interrupt
#define IER_CAN1XBYTE[CS1_SJA1000+4]//interrupt enable //Peli
#define BTR0_CAN1XBYTE[CS1_SJA1000+6] //bus timing0
#define BTR1_CAN1XBYTE[CS1_SJA1000+7] //bus timing1
#define OCR_CAN1XBYTE[CS1_SJA1000+8]
#define TEST_CAN1XBYTE[CS1_SJA1000+9]
#define ECC_CAN1XBYTE[CS1_SJA1000+12]//error catch
#define EWLR_CAN1XBYTE[CS1_SJA1000+13]//error warning limit
#define RXERR_CAN1XBYTE[CS1_SJA1000+14]//
#define TXERR_CAN1XBYTE[CS1_SJA1000+15]
#define ACR0_CAN1XBYTE[CS1_SJA1000+16]
#define ACR1_CAN1XBYTE[CS1_SJA1000+17]
#define ACR2_CAN1XBYTE[CS1_SJA1000+18]
#define ACR3_CAN1XBYTE[CS1_SJA1000+19]
#define AMR0_CAN1XBYTE[CS1_SJA1000+20]
#define AMR1_CAN1XBYTE[CS1_SJA1000+21]
#define AMR2_CAN1XBYTE[CS1_SJA1000+22]
#define AMR3_CAN1XBYTE[CS1_SJA1000+23]
#define RBSA_CAN1XBYTE[CS1_SJA1000+30]//beginning of receive
#define CDR_CAN1XBYTE[CS1_SJA1000+31]//clock devide

#define TXFrameInfo1 XBYTE[CS1_SJA1000+16]
#define TXID1 XBYTE[CS1_SJA1000+17]
#define TXID2 XBYTE[CS1_SJA1000+18]
#define TXID3 XBYTE[CS1_SJA1000+19]
#define TXID4 XBYTE[CS1_SJA1000+20]
#define TXDATA1 XBYTE[CS1_SJA1000+21]
#define TXDATA2 XBYTE[CS1_SJA1000+22]
#define TXDATA3 XBYTE[CS1_SJA1000+23]
#define TXDATA4 XBYTE[CS1_SJA1000+24]
#define TXDATA5 XBYTE[CS1_SJA1000+25]
#define TXDATA6 XBYTE[CS1_SJA1000+26]
#define TXDATA7 XBYTE[CS1_SJA1000+27]
#define TXDATA8 XBYTE[CS1_SJA1000+28]

#define RXFrameInfo1 XBYTE[CS1_SJA1000+16]
#define RXID1 XBYTE[CS1_SJA1000+17]
#define RXID2 XBYTE[CS1_SJA1000+18]
#define RXID3 XBYTE[CS1_SJA1000+19]
#define RXID4 XBYTE[CS1_SJA1000+20]
#define RXDATA1 XBYTE[CS1_SJA1000+21]
#define RXDATA2 XBYTE[CS1_SJA1000+22]
#define RXDATA3 XBYTE[CS1_SJA1000+23]
#define RXDATA4 XBYTE[CS1_SJA1000+24]
#define RXDATA5 XBYTE[CS1_SJA1000+25]
#define RXDATA6 XBYTE[CS1_SJA1000+26]
#define RXDATA7 XBYTE[CS1_SJA1000+27]
#define RXDATA8 XBYTE[CS1_SJA1000+28]

#defineGoToRESET0x01
#defineReleaseRXBuf0x04
#defineRequest_TX0x01

#defineNOT0
#defineYES1
//4800bps 5bits 1.04mS
#define TIME_MS1
#define temp_TH0(0 – 922*TIME_MS)/256
#define temp_TL0(0 – 922*TIME_MS)%256

sbit LED1 = P1^2;
sbit LED2 = P1^3;
sbit LED3 = P1^5;
sbit LED4 = P1^4;
sbit WDT = P3^4;

void System_init(void);
void Delay(unsigned char time);
void W_WDT(void);
void Interrupt_init(void);
void CAN_init(void);
//void CAN_Transmit(unsigned char Farmeinfo);
void CAN_Transmit(bit FarmeType);
void CAN_Receive(void);
void Timer_init(void);
void UART_ini(void);
void UART_Send_Byte(unsigned char Data);
void UART_Transmit(void);
void Clear_Buffer(unsigned char *pointer,unsigned char length);

#endif

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/zhishi/262963.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部