国产化项目需要调试国产单片机 js407 和国产CAN独立控制器 smsja1000。
js407完全适配stm32f407,可直接下载stm32f407的代码。
smsja1000完全适配sja1000,可直接替换。
以下使用默认模式BasicCAN,不支持扩展帧模式。
总体来说,和stm32的CAN控制器一样,需要配置一些寄存器,模式,中断,波特率,屏蔽码等。
需要注意哪些寄存器是在复位模式或者工作模式中可用。
1.8080接口的写时序如下:
void sja1000_write_cmd(uint8_t addr, uint8_t cmd) //can 写寄存器数据
{
uint8_t i;
adio_out_change(); //切换数据io为输出
CAN_ALE_H; //写命令地址
for(i=0; i<8; i++)
{
if(addr & 0x80)
GPIO_SetBits(CAN_AD_Port, adIOPin[i]);
else
GPIO_ResetBits(CAN_AD_Port, adIOPin[i]);
addr <<= 1;
}
CAN_ALE_L;
CAN_CS_L; //写命令
CAN_WR_L;
for(i=0; i<8; i++)
{
if(cmd & 0x80)
GPIO_SetBits(CAN_AD_Port, adIOPin[i]);
else
GPIO_ResetBits(CAN_AD_Port, adIOPin[i]);
cmd <<= 1;
}
CAN_WR_H;
CAN_CS_H;
}
2.读时序如下:
uint8_t sja1000_read_byte(uint8_t addr) //can 读寄存器数据
{
uint8_t i,data=0;
adio_out_change(); //切换数据io为输入
CAN_ALE_H; //写命令地址
for(i=0; i<8; i++)
{
if(addr & 0x80)
GPIO_SetBits(CAN_AD_Port, adIOPin[i]);
else
GPIO_ResetBits(CAN_AD_Port, adIOPin[i]);
addr <<= 1;
}
CAN_ALE_L;
adio_in_change();
CAN_CS_L; //读8位数据
CAN_RD_L;
for(i=0; i<8; i++)
{
data <<= 1;
if(GPIO_ReadInputDataBit(CAN_AD_Port,adIOPin[i]))
data++;
}
CAN_RD_H;
CAN_CS_H;
return data;
}
3.初始化寄存器配置如下:
uint8_t can_filter[8] = {0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff};
void sja1000_reg_Init(void)
{
uint8_t i,test=0;
CAN_RESET_L;
CAN_ALE_L;
CAN_WR_H;
CAN_RD_H;
CAN_CS_H;
delay_ms(1);
CAN_RESET_H;
sja1000_write_cmd(0x00, 0x01); // 复位模式
sja1000_write_cmd(0x06, 0x00); // 配置总线定时器 0
sja1000_write_cmd(0x07, 0x1C); // 配置总线定时器 1
sja1000_write_cmd(0x08, 0xFA); // 配置输出管脚为 TX0 与 RX0,推挽输出
sja1000_write_cmd(0x04, 0x00); // 验收
sja1000_write_cmd(0x05, 0xFF); // 屏蔽
sja1000_write_cmd(0x00, 0x02); // 工作模式+接收中断
}
4.发送帧数据如下:
/* CMR 命令 addr 0x01
CMR.4 自接收 1/0
*/
uint8_t msg[10] = {0x00,0xE8,0x01,0x03,0x04,0x05,0x06,0x07,0x08,0x09};
void sja1000_send_frame(void)
{
uint8_t i;
msg[2]++;
for(i=0;i<10;i++)
{
sja1000_write_cmd(0x0A+i,msg[i]); //发送缓冲区
}
sja1000_write_cmd(0x01,0x01); //发送请求
}
5.利用sja1000的中断线配置中断接受数据:
uint8_t msgbuf[8]={0};
void EXTI2_IRQHandler(void) //外部中断2服务程序
{
uint8_t data=0,i;
data = sja1000_read_byte(0x03);
if(data & 0x01)
{
for(i=0;i<8;i++)
{
msgbuf[i] = sja1000_read_byte(22+i);
}
sja1000_write_cmd(0x01,0x04); //清除接收husn
sja1000_send_frame();
}
EXTI_ClearITPendingBit(EXTI_Line2);//清除LINE2上的中断标志位
}