新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > AVR單片機(jī)實(shí)現(xiàn)了232到CAN轉(zhuǎn)換

AVR單片機(jī)實(shí)現(xiàn)了232到CAN轉(zhuǎn)換

作者: 時(shí)間:2016-11-27 來源:網(wǎng)絡(luò) 收藏
#define TXREQ_SET 0x08
#define TXREQ_CLEAR 0x00
#define TXP_HIGHEST 0x03
#define TXP_INTER_HIGH 0x02
#define TXP_INTER_LOW 0x01
#define TXP_LOWEST 0x00
#define DLC_0 0x00
#define DLC_1 0x01
#define DLC_2 0x02
#define DLC_3 0x03
#define DLC_4 0x04
#define DLC_5 0x05
#define DLC_6 0x06
#define DLC_7 0x07
#define DLC_8 0x08
#define CAN_RESET 0xC0
#define CAN_READ 0x03
#define CAN_WRITE 0x02
#define CAN_RTS 0x80
#define CAN_RTS_TXB0 0x81
#define CAN_RTS_TXB1 0x82
#define CAN_RTS_TXB2 0x84
#define CAN_RD_STATUS 0xA0
#define CAN_BIT_MODIFY 0x05
#define CAN_RX_STATUS 0xB0
#define CAN_RD_RX_BUFF 0x90
#define CAN_LOAD_TX 0X40
#define DUMMY_BYTE 0x00
#define TXB0 0x31
#define TXB1 0x41
#define TXB2 0x51
#define RXB0 0x61
#define RXB1 0x71
#define EXIDE_SET 0x08
#define EXIDE_RESET 0x00
uchar can_boud=0x07;//MCP2515在16M晶振情況,can_boud=0x00總線波特率為1M,0x01=500K,0x03=250K,0x07=125K;公式:16M/(16*(1+X))
uint bps=38400;//定義avr單片機(jī)串口波特率
uchar eflag=0;//是不是擴(kuò)展幀,為1則表示接收到的是擴(kuò)展幀,0表示標(biāo)準(zhǔn)幀
uchar Tdate[10]={0};//存放要發(fā)送標(biāo)準(zhǔn)幀的數(shù)據(jù),最大10位,前2位是ID號,后8位是數(shù)據(jù)位
uchar TID[2]={0,0};//存放要發(fā)送標(biāo)準(zhǔn)幀的ID號
uchar Rdate[8]={0};//存放接收到的數(shù)據(jù)
uchar RESID[4];//存放接收到的數(shù)據(jù)幀的ID號,標(biāo)準(zhǔn)幀只用到RESID[0],RESID[1],擴(kuò)展幀全部用到
uchar bytetime;//232與CAN透明轉(zhuǎn)換時(shí),根據(jù)不同的波特率確定所要延時(shí)的時(shí)間,
uint usart_number=0;//計(jì)數(shù)當(dāng)前所接收的串行數(shù)據(jù)的那一組數(shù)據(jù)流的數(shù)據(jù)個(gè)數(shù),串口傳來的數(shù)據(jù)存放在Tdate中等待用CAN標(biāo)準(zhǔn)幀發(fā)送
uchar state;//2515狀態(tài)(包括發(fā)送接收中斷標(biāo)志位和各請求發(fā)送位),具體見數(shù)據(jù)手冊
uchar DLC=8;//接收到數(shù)據(jù)的長度
//
//
void delay(uchar k)//
{uint i=0;
while(k--){for(i=0;i<8000;i++);}
}
//##############################################################################
void Set_CS(uchar level) //
{if(level) PORTB|=0x10; //
else PORTB&=0xef; //
}
//##############################################################################
//
//
void WriteSPI(uchar order)
{ uchar clear;
Set_CS(0); //
SPDR=order; //2515讀指令為0x03
while(!(SPSR&0x80)); //等待SPIF置位,等數(shù)據(jù)發(fā)送完畢
clear=SPSR;
clear=SPDR;//
Set_CS(1); //
}
//
uchar Read_state(uchar order)//讀狀態(tài)命令,order=0xa0,0xa1,
{ uchar clear;
Set_CS(0); //
SPDR=order; //
while(!(SPSR&0x80)); //等待SPIF置位,等數(shù)據(jù)發(fā)送完畢
clear=SPSR;
clear=SPDR;//
SPDR=0; //空數(shù)據(jù)
while(!(SPSR&0x80));//等待SPIF置位,等數(shù)據(jù)發(fā)送完畢
clear=SPSR;
clear=SPDR; //通過先讀SPSR,緊接著訪問SPDR來對SPIF清零
Set_CS(1); //
return clear;
}
//
uchar Read_Byte(uchar Address)
{uchar clear;
uchar date;
Set_CS(0); //使能SPI器件
SPDR=0x03; //送2515讀指令為0x03
while(!(SPSR&0x80)); //等待SPIF置位,等數(shù)據(jù)發(fā)送完畢
clear=SPSR;
clear=SPDR; //通過先讀SPSR,緊接著訪問SPDR來對SPIF清零
SPDR=Address; //送地址
while(!(SPSR&0x80));
clear=SPSR;
clear=SPDR;
SPDR=0x00; //發(fā)空數(shù)據(jù),啟動(dòng)數(shù)據(jù)發(fā)送以接收數(shù)據(jù)
while(!(SPSR&0x80));
clear=SPSR;
clear=SPDR;
date=SPDR; //接收數(shù)據(jù)
Set_CS(1); //關(guān)SPI器件DS1722
return date;
}
//
void Write_Byte(uchar Address,uchar Data)
{uchar clear;
Set_CS(0); //使能SPI器件2515
SPDR=0x02; //送2515寫命令為0x02
while(!(SPSR&0x80));//等待SPIF置位,等數(shù)據(jù)發(fā)送完畢
clear=SPSR;
clear=SPDR;
SPDR=Address; //送地址,啟動(dòng)SPI時(shí)鐘
while(!(SPSR&0x80));//等待SPIF置位,等數(shù)據(jù)發(fā)送完畢
clear=SPSR;
clear=SPDR; //通過先讀SPSR,緊接著訪問SPDR來對SPIF清零
SPDR=Data;
while(!(SPSR&0x80));
clear=SPSR;
clear=SPDR;
Set_CS(1); //關(guān)SPI器件
}
//
//###########################對CAN的一些操作####################################
//
void load_Standard_ID_dates(uchar num)//給標(biāo)準(zhǔn)幀裝載ID和數(shù)據(jù)
//選用發(fā)送緩沖器0,num:要發(fā)送的個(gè)數(shù)(最大8個(gè))
{
uchar i,j,T0=0x36;
uchar TIDH,TIDL;
i=TID[1]>>3;j=TID[0]<<5;j=j+i;i=TID[1]<<5;
TIDL=i;TIDH=j;//將數(shù)組TID中的值轉(zhuǎn)化為TIDH,TIDL以便給TXB0SIDH,TXB0SIDL附值
Write_Byte(CANCTRL,0x80);//CAN工作在配置模式
Write_Byte(CNF1,can_boud);
Write_Byte(TXB0SIDH,TIDH);
Write_Byte(TXB0SIDL,TIDL);
Write_Byte(TXB0DLC,num);//
for(i=2;i
}
//##############################################################################
void Receive_all_ID_process(void)//結(jié)合MCP2515數(shù)據(jù)手冊來看
{uchar k;
k=RESID[1];//先判斷接收到的是不是標(biāo)準(zhǔn)幀,因?yàn)闃?biāo)準(zhǔn)幀和擴(kuò)展幀的ID處理不一樣
if((k&0x08)==0)
{//如果是標(biāo)準(zhǔn)處理方法
RESID[1]=RESID[1]>>5;
k=RESID[0]&0x1f;//借用k
k=k<<3;
RESID[1]=RESID[1]+k;
RESID[0]=RESID[0]>>5;
}
else
{//擴(kuò)展幀處理方法,RESID[3]、RESID[4]不變
k=k>>5;
k=k<<2;
RESID[1]=RESID[1]&0x03;
RESID[1]=RESID[1]+k;
k=RESID[0];
k=k<<5;
RESID[1]=RESID[1]+k;
RESID[0]=RESID[0]>>3;//將RXB0SIDH,RXB0SIDL轉(zhuǎn)化
}
}
//##############################################################################
//##############################USART初始化程序###########################//
void usart_init(void)
{
UCSRB=(1<
UBRRL=(fosc/16/(bps+1))%6;
UBRRH=(fosc/16/(bps+1))/256;
UCSRC=(1<
bytetime=215983/bps;//215983=1000000*20/92.6,92.6=1024/11.0592,定時(shí)器分頻為1024
bytetime=255-bytetime;//計(jì)算不同的波特率所要延時(shí)的初值,要附值給TCNT0,實(shí)現(xiàn)透明轉(zhuǎn)換中用到
}
//##########################串行通信##########################//
void putchar(uchar c)
{while(!(UCSRA&(1<
UDR=c;}
//##############################中斷服務(wù)程序##################################//
void INT1_17(void)
{
uchar i,j,k,R0=0x66;
GICR &=0x7f;
state=Read_state(0xa0);
//WriteSPI(0xa0);//讀取2515狀態(tài)指令,狀態(tài)值附值給state
if((state&0x01)!=0)
{//判斷是不是接收緩沖器0滿產(chǎn)生的中斷
k=Read_Byte(RXB0SIDL);//為了判斷是標(biāo)準(zhǔn)幀還是擴(kuò)展幀
if((k&0x08)==0)eflag=0;//置標(biāo)準(zhǔn)幀標(biāo)志
else eflag=1;//置擴(kuò)展幀標(biāo)志
DLC=Read_Byte(RXB0DLC);
DLC &=0x0f;
RESID[0]=Read_Byte(RXB0SIDH);
RESID[1]=Read_Byte(RXB0SIDL);
RESID[2]=Read_Byte(RXB0EID8);
RESID[3]=Read_Byte(RXB0EID0);//先讀取所有ID
Receive_all_ID_process();//處理RESID
for(i=0;i
if(eflag==0)
{//如果是標(biāo)準(zhǔn)幀
putchar(RESID[0]);
putchar(RESID[1]);//先送標(biāo)準(zhǔn)幀ID號
}
else
{//如果是擴(kuò)展幀
putchar(RESID[0]);
putchar(RESID[1]);
putchar(RESID[2]);
putchar(RESID[3]);//先送擴(kuò)展幀ID號
}
putchar(DLC);
for(i=0;i
}
Write_Byte(CANINTF,0x00);//接收完一次必須對中斷標(biāo)志位清0
GICR |=0x80;
}
//####################################
void Usart_receive(void)//定義接收中斷服務(wù)程序
{Tdate[usart_number]=UDR;
usart_number++;
TIMSK=0x05;//打開T1,T0中斷屏蔽
TCCR0=0x05;//設(shè)T0分頻數(shù)為1024
TCNT0=bytetime;//設(shè)T0時(shí)間常數(shù),從此值開始計(jì)數(shù)
}
//##############定時(shí)器中斷0,串行數(shù)據(jù)流控制
void Timer0(void)
{TIMSK=0x00;//關(guān)T0中斷屏蔽
TCNT0=0x00;//
TCCR0=0x00;//T0停止計(jì)數(shù)
if((usart_number>2)&&(usart_number<11))
{
TID[0]=Tdate[0];TID[1]=Tdate[1];
load_Standard_ID_dates(usart_number-2);//對2515發(fā)送緩沖器0和ID寄存器進(jìn)行數(shù)據(jù)裝載
usart_number=0;
Write_Byte(CANCTRL,0x00);//選定工作模式
WriteSPI(CAN_RTS_TXB0);//發(fā)送緩沖器0請求發(fā)送
}
else usart_number=0;
}
//##############################CAN(2515)初始化程序###########################//
void CAN_Initialize(void)
{
WriteSPI(CAN_RESET);
delay(20);
Write_Byte(CANCTRL,0x80);//CAN工作在配置模式
Write_Byte(CNF1,can_boud);
Write_Byte(CNF2,0x80 | PHSEG1_3TQ | PRSEG_1TQ);//Set CNF2
Write_Byte(CNF3,PHSEG2_3TQ);
//0x80+0x10+0x00,相位緩沖段2由CNF3確定,相位緩沖段1為3TQ,傳播段為1TQ
Write_Byte(RXB0CTRL,0xf0);//接收類型選擇,接收所有報(bào)文
Write_Byte(CANINTF,0x00);//接收完一次必須對中斷標(biāo)志位清0
Write_Byte(CANINTE,0x01);//接收緩沖器0滿中斷使能
Write_Byte(CANCTRL,0x00);//選定正常工作模式
}
//##############################系統(tǒng)初始化程序################################//
void AVR_Initialize(void) //初始化
{
DDRB=0xff; //SPI口
PORTB=0xff;
DDRD=0xf0;//將外部中斷引腳設(shè)定為輸入
PORTD=0x7f;
SPCR=0b01011100;//關(guān)中斷(SPIE=0),使能SPI(SPE=1),MSB首先發(fā)送(DORD=0)
//選擇微機(jī)為主機(jī)模式(MSTR=1)
//空閑時(shí)SCK 為高電平(CPOL=1)
//在SCK 的結(jié)束沿采樣(CPHA=1)以保證數(shù)據(jù)穩(wěn)定
//SPR1=0和SPR0=0,SCK=fosc/4
SPSR |=0x01;//SPI的速度加倍
MCUCR=0x0a;//設(shè)置外部中斷的中斷觸發(fā)方式為下降沿觸發(fā)
GICR=0xc0;//通用中斷控制寄存器設(shè)置,打開中斷INT0和INT1
SREG=0x80;//開全局中斷
}
//##################################主程序####################################//
void main()
{
AVR_Initialize(); //I/O口及中斷初始化
CAN_Initialize();
usart_init();
UCSRB |=0x80;//接收中斷使能
}


上一頁 1 2 下一頁

關(guān)鍵詞: AVR單片機(jī)232CAN轉(zhuǎn)

評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉