📄 can-rs232.c
字号:
#include <avr/wdt.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define uchar unsigned char
#define uint unsigned int
#include <avr/delay.h>
uchar can_data[2][8];
uchar cReceiveBuf[8];
//减1数据接收计数器的初始值
#define RECEIVE_COUNTER_INIV 0x08
//接收状态标志,gReceiveFlag=0x01表示一帧数据接收完成
uchar gReceiveFlag;
//接收缓冲区的指针
uchar *gReceivePointer;
//串口接收缓冲区
uchar gReceiveBuf[8];
//接收计数器,用于判断一帧数据是否接收完
uchar gReceiveCounter;
//用于存放前一次中断发生时接收到的数据。如果前次接收到的数据为A5,则该变量的值
//为A5,否则为0
uchar gPreByteReceive;
void usart_init(void)
{
/* set baud rate 4800*/
UBRR0H=0;
UBRR0L=103;
UCSR0B=(1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);
/* set frame format:8 data,2 stop bit*/
UCSR0C=(1<<USBS0)|(3<<UCSZ0);
}
void mcu_init(void)
{
// WDTCR = (1<<WDCE) | (1<<WDE); //2行看门狗初始化
//WDTCR = 0x0f; //0x1c=0.25s 0x1d=0.5s
//// __watchdog_reset(); //喂狗
//wdt_reset();
//-------------------prot init---------
//ORTA = 0xfe;
DDRA = 0xFF; //端口设置:PA设置为输出
//---------------- MCU interrupt -------
SREG = 0x00; //关全局中断; 0x80开全局中断
CANGCON |= (1<<SWRES); //CAN控制器软复位
CANBT1 = 0x06; ///设置系统时钟 //设置波特率分频因子16MHz,16TQ,250k,=4=3+1,3
CANBT2 = 0x0c; //补偿不同CAN控制器之间的相位差和物理延时 //同步段为1“0x0n”传播段=7=6+1
CANBT3 = 0x37; //相位缓冲PH2=4=3+1,PH1=4=3+1
CANTCON = 0xff; //预比例因子
//--------------can_MOB INITIAL---------------
//MOB0=RX[CMD] 接收上位机发来的指令 格式:3,0,0,177,239,33
CANPAGE = 0x00; //选择邮箱和增长方式 //选择邮箱0,自动增量,初值为0
CANSTMOB = 0; //CAN Mob状态寄存器,控制.DLC寄存器需要初始化
CANCDMOB = 0x08; //can2A,DLC=8
CANIDT4 = 0x00;
CANIDT3 = 0x00;
CANIDT2 = 0x80; // 100 000000
CANIDT1 = 0x00; // 000 000000 该节点ID为4
CANIDM4 = 0x00;
CANIDM3 = 0x00;
CANIDM2 = 0x00;
CANIDM1 = 0x00;
//MOB1=TX[STA1] 向上位机报告状态组1 6,0,0,178,239,33
CANPAGE = 0x10; //选择邮箱1,自动增长,初值为0
CANSTMOB = (1<<TXOK);
CANCDMOB = 0x08;
CANIDT4 = 0x00; //
CANIDT3 = 0x00; //
CANIDT2 = 0x20; // 001 000000 1
CANIDT1 = 0x01; // 000 0000 1 该节点ID为9
CANGIE |= ((1<<ENIT) + (1<<ENRX)); //开全局中断和接收中断
CANIE2 |= 0x01; //开MOB0信箱接收中断(接收邮箱)
CANPAGE = 0x00;
CANCDMOB |= 0x80; //MOB0接收使能
CANGCON |= 0x02; //CAN控制器启动,连续的11个电平之后进入读取数据状态
SREG = 0x80; //开全局中断
}
void USART0_Transmit (unsigned char data)
{
/*wait for empty transmit buffer*/
while ( ! (UCSR0A&(1<<UDRE0)));
/*Put data into buffer ,sends the data*/
UDR0= data;
}
void MOB_send (uchar n)
//void MOB_send(void)
{
CANGIE &= ~(1<<ENRX);
uint i,j;
CANPAGE = (n<<4); //MOB_n, auto increment, index 0
if (CANSTMOB & (1<<TXOK))
{
CANCDMOB= 0x08; //设置协议类型和数据长度
CANSTMOB &= ~(1<<TXOK); //禁止TXOK,开始发送数据
for(i =0; i < 8; i++) //发送8个数据字节
{
CANMSG = gReceiveBuf[i];
PORTA = gReceiveBuf[i]; // 每发送完一个字节即通过A口显示
for( j =0; j < 40; j++) { _delay_ms(500);}
}
CANCDMOB = 0x48; //帧发送
CANGIE |=(1<<ENRX);
}
}
ISR(USART0_RX_vect)
{ uint i,j;
//UCSR0B=(0<<RXEN0)|(1<<TXEN0);//关串口接收中断
unsigned char ByteReceive;
ByteReceive = UDR0;
//以下判断接收到的一个字节的数据是否为0xa5
if (ByteReceive == 0xa5)
{
// gPreByteReceive = 0xa5;
gReceivePointer = gReceiveBuf;
}
else
{ if (ByteReceive==0x5a)
{
//uint i,j;
PORTA =0xaa; for( j =0; j < 20; j++) { _delay_ms(500);} //准备发送信号 1010 1010
PORTA =0x55; for( j =0; j < 20; j++) { _delay_ms(500);} //准备发送信号 0101 0101
for( i =0; i < 8; i++)
{
PORTA = gReceiveBuf[i]; //先显示要发送的8个数据字节
for( j =0; j < 20; j++) { _delay_ms(500);}
//gReceiveBuf[i]=0;
}
}
else
{
// gReceivePointer = gReceiveBuf;
*gReceivePointer = ByteReceive;
gReceivePointer++;
// *gReceivePointer ++ = ByteReceive; //????????
}
}
}
ISR(CANIT_vect)
{
uchar i = 1, num_i,j;
CANGIE &= ~(1<<ENRX); //关接收中断****
CANSIT2=0x01;
num_i = CANSIT2; ///中断的邮箱号
i=0; ///零号邮箱中断
TCNT1 = 0x0000; //重启定时监视器,计数器清零
CANPAGE = i<<4;
//////对应0#接受邮箱////////
for(num_i = 0; num_i < 8; num_i++)
{
cReceiveBuf[num_i]=CANMSG; //取得8个字节的数据
}
CANPAGE = 0x00;
CANSTMOB &= ~(1<<RXOK); //清中断标志****
CANCDMOB = 0x88; //接收使能
//准备发送
PORTA =0xaa; for( j =0; j < 20; j++) { _delay_ms(500);} //准备发送信号 1010 1010
PORTA =0x55; for( j =0; j < 20; j++) { _delay_ms(500);} //准备发送信号 0101 0101
for( num_i = 0; num_i < 8; num_i++)
{
PORTA = cReceiveBuf[num_i]; //先显示要发送的8个数据字节
_delay_ms(500);
}
//取得字节后由串口发送
for(num_i=0;num_i<2;num_i++) //先发送起始2个字节“A5”
{
USART0_Transmit(0xa5);
PORTA = 0xa5; for( j =0; j < 20; j++) { _delay_ms(500);}
}
for(num_i=0;num_i<8;num_i++) //再发送8个数据字节
{
USART0_Transmit(cReceiveBuf[num_i]);
PORTA = cReceiveBuf[num_i]; for( j =0; j < 20; j++) { _delay_ms(500);}
}
CANGIE |= (1<<ENRX); //开中断 ,允许接收
}
void main()
{
mcu_init();
usart_init( );
gPreByteReceive=0x00;
gReceiveFlag=0x00;
uint i=0,j;
PORTA =0xaa; for( j =0; j < 20; j++) { _delay_ms(500);} //准备发送信号 1010 1010
PORTA =0x55; for( j =0; j < 20; j++) { _delay_ms(500);} //准备发送信号 0101 010
for(i=0;i<8;i++)
{ cReceiveBuf[i]=i+1;}
for(i=0;i<8;i++) //再发送8个数据字节
{
USART0_Transmit(cReceiveBuf[i]);
PORTA = cReceiveBuf[i]; for( j =0; j < 20; j++) { _delay_ms(500);}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -