📄 pic18f4580_can_rs232_picc8.35.c
字号:
//Function(函数功能): 串口初始化,波特率:9600bps //
//Input(输入参数类型):void //
//Output(输出参考类型):void //
//Return(返回信息):无 //
//////////////////////////////////////////////////////////////////////////
void InitUSART(void)
{
TRISC6 = 0; //RC6-TX
TRISC7 = 1; //RC7-RX
BAUDCON=0x00; //8位波特率发生器
SPBRG = ((Fosc/BAUDRATE)/64)-1; //8位,异步,低速
TXSTA = 0b00100010; //异步模式,8位发送,发送使能,低速
RCSTA = 0b10010000; //使能串口,8位接收,使能连续接收
RCIF = 0; //串口接收中断标志清零
RCIE = 1; //使能串口接收中断
RCIP = 0; //低优先级
NOP();
}
//************************************************************************
//////////////////////////////////////////////////////////////////////////
// 子函数 //
//Function name(函数名称):InitTMR0 //
//Create date(创建日期):2007.8.1 //
//created by(创建人):夏红峰 //
//E-mail:master_0722@sina.com/master_0722@yahoo.com //
//Function(函数功能):用于确定串口数据流的长度 //
//Input(输入参数类型):void //
//Output(输出参考类型):void //
//Return(返回信息):无 //
//////////////////////////////////////////////////////////////////////////
void InitTMR0(void)
{
//禁止TMR0,8位定时器/计数器,内部指令周期时钟,使用前分频器,1:128分频
T0CON = 0b01010110;
TMR0IF = 0; //TMR0中断标志位清零
TMR0IE = 1; //TMR0中断使能
TMR0IP = 1; //TMR0中断优先级高
TMR0 = TMR0data; //延时3个串口接收到的字节
NOP();
}
//************************************************************************
//////////////////////////////////////////////////////////////////////////
// 子函数 //
//Function name(函数名称):InitCAN //
//Create date(创建日期):2007.8.1 //
//created by(创建人):夏红峰 //
//E-mail:master_0722@sina.com/master_0722@yahoo.com //
//Function(函数功能): CAN初始化 //
//Input(输入参数类型):void //
//Output(输出参考类型):void //
//Return(返回信息):无 //
//////////////////////////////////////////////////////////////////////////
void InitCAN(void)
{
TRISB2 = 0; //设置CANRX-RB3输入,CANTX-RB2输出
TRISB3 = 1;
CANCON_0 = 0x80; //请求进入CAN配置模式,REQOP=100
while(( CANSTAT_0 & 0b11100000 ) != 0x80){;} //等待进入CAN配置模式OPMODE=100
//设置CAN波特率125kbps,在Fosc=20MHz时,Tbit=8us,假设BRP=09h
//则Tq=[2*(1+BRP)]/Fosc=2*(1+9)/(20MHz)=1us
//normal bit rate=8Tq,SJW=00,Sync_Seg=1Tq,Prog_Seg=1Tq
//Phase_Seg1=3Tq,Phase_Seg2=3Tq
BRGCON1 = 0x09;
BRGCON2 = 0x90;
BRGCON3 = 0x42;
RXB0CON = 0x60; //接收所有有效信息,这样就不需要设置过滤屏蔽器了
RXB1CON = RXB0CON; //做同样处理
CIOCON = 0x00; //当“隐性”时,CANTX引脚驱动到高阻状态,禁止CAN捕捉
ECANCON=0x00; //选择模式0
CANCON_0 = 0x00; //请求正常方式
while((CANSTAT_0&0x80) != 0x80){;} //等待进入正常模式
//初始化CAN的中断,PIR3为CAN的外围中断标志寄存器
RXB0IF = 0; //CAN接收缓冲器0中断标志位清零
RXB0IE = 1; //使能CAN接收缓冲器0的接收中断
RXB0IP = 1; //接收缓冲器0的接收中断为高优先级
NOP();
}
//************************************************************************
//////////////////////////////////////////////////////////////////////////
// 主程序 //
//////////////////////////////////////////////////////////////////////////
void main(void)
{
unsigned char sendnum;
NOP();
Initial(); //IO口初始化
InitUSART(); //串口初始化
InitTMR0(); //定时器0初始化
InitCAN(); //内部CAN寄存器设置初始化
IPEN = 1; //使能中断优先级
INTCON |= 0xC0; //开放所有高低优先级中断
while(1)
{
if(RD0 == 0) //如有S1按键按下,发送标准帧
{
while(RD0 == 0); //等待S1按键释放
TXB0CON = 0x03; //设置为发送最高优先级
TXB0SIDH = 0xFF; //SID10--SID3
TXB0SIDL = 0xE0; //SID2--SID0
TXB0DLC = 0x08; //发送数据长度为8字节
TXB0D0=0x00; //发送的数据
TXB0D1=0x11;
TXB0D2=0x22;
TXB0D3=0x33;
TXB0D4=0x44;
TXB0D5=0x55;
TXB0D6=0x66;
TXB0D7=0x77;
TXB0REQ = 1; //请求发送
while(TXB0REQ == 1); //等待发送成功
RD1 = 1; //发送成功,则点亮RD1
DelayNmSec(100); //延时0.1s
RD1 = 0; //熄灭RD1
}
if(RC0 == 0) //如有S2按键按下,发送扩展帧
{
while(RC0 == 0); //等待S2按键释放
TXB0CON = 0x03; //设置为发送最高优先级
TXB0SIDH = 0xFF; //EID28--21
TXB0SIDL = 0xEB; //EID20--EID18,扩展帧使能,EID17--EID16
TXB0EIDH = 0xFF; //EID15--EID8
TXB0EIDL = 0xFF; //EID7--EID0
TXB0DLC = 0x08; //发送数据长度为8字节
TXB0D0=0x00; //发送的数据
TXB0D1=0x11;
TXB0D2=0x22;
TXB0D3=0x33;
TXB0D4=0x44;
TXB0D5=0x55;
TXB0D6=0x66;
TXB0D7=0x77;
TXB0REQ = 1; //请求发送
while(TXB0REQ == 1); //等待发送成功
RC1 = 1; //发送成功,则点亮RC1
DelayNmSec(100); //延时0.1s
RC1 = 0; //熄灭RC1
}
if(USARTreceive_flag == 1) //接收到符合要求的串口数据流
{
USARTreceive_flag = 0; //串口转发再允许
TXB0CON = 0x03; //设置为发送最高优先级
pointer = &receive232[1];
TXB0SIDH = *pointer++; //发送的标识符
TXB0SIDL = *pointer++;
TXB0EIDH = *pointer++;
TXB0EIDL = *pointer++;
TXB0DLC = *pointer++; //发送的数据长度
TXB0D0 = *pointer++; //发送的数据
TXB0D1 = *pointer++;
TXB0D2 = *pointer++;
TXB0D3 = *pointer++;
TXB0D4 = *pointer++;
TXB0D5 = *pointer++;
TXB0D6 = *pointer++;
TXB0D7 = *pointer++;
TXB0REQ = 1; //请求发送
while(TXB0REQ == 1); //等待发送成功
if(TXB0EXIDE == 0)//如果是标准帧
{
RD1 = 1; //发送成功,则点亮RD1
DelayNmSec(100); //延时0.1s
RD1 = 0; //熄灭RD1
}
if(TXB0EXIDE == 1)//如果是扩展帧
{
RC1 = 1; //发送成功,则点亮RC1
DelayNmSec(100); //延时0.1s
RC1 = 0; //熄灭RC1
}
}
if(CANreceive_flag == 1) //接收到来自CAN总线的数据
{
CANreceive_flag = 0; //接收标志位清零
send232[0] = RXB0SIDH; //接收到的标准标识符高字节
send232[1] = RXB0SIDL; //接收到的标准标识符低字节
send232[2] = RXB0EIDH; //接收到的扩展标识符高字节(看RXB0EXID而定)
send232[3] = RXB0EIDL; //接收到的扩展标识符低字节(看RXB0EXID而定)
send232[4] = RXB0DLC; //接收到的数据长度
send232[5] = RXB0D0; //接收到的数据
send232[6] = RXB0D1;
send232[7] = RXB0D2;
send232[8] = RXB0D3;
send232[9] = RXB0D4;
send232[10] = RXB0D5;
send232[11] = RXB0D6;
send232[12] = RXB0D7;
if(RXB0EXID == 0) //标准帧的话
{
RD1 = 1; //接收成功,则点亮RD1
DelayNmSec(100); //延时0.1s
RD1 = 0; //熄灭RD1
}
if(RXB0EXID == 1) //扩展帧的话
{
RC1 = 1; //接收成功,则点亮RC1
DelayNmSec(100); //延时0.1s
RC1 = 0; //熄灭RC1
}
send_count=13; //串口转发13字节
for(sendnum=0;sendnum<send_count;sendnum++) //转发到串口
{
TXREG = send232[sendnum];
while(TRMT == 0); //等待串口发送完一字节
}
}
}
}
//************************************************************************
//////////////////////////////////////////////////////////////////////////
// 子函数 //
//Function name(函数名称):DelayNmSec //
//Create date(创建日期):2007.8.1 //
//created by(创建人):夏红峰 //
//E-mail:master_0722@sina.com/master_0722@yahoo.com //
//Function(函数功能): 延时N*1ms,最大65.5秒 //
//Input(输入参数类型):unsigned int N //
//Output(输出参考类型):void //
//Return(返回信息):无 //
//////////////////////////////////////////////////////////////////////////
void DelayNmSec(unsigned int N)
{
unsigned int j;
while(N--)
for(j=0;j<MILLISEC;j++);
}
//************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -