📄 sja1000.c
字号:
//***************************************************************************************************
//描 述:独立CAN控制器SJA1000基本的函数定义(PeliCAN 查询工作方式),需引用time.c文件. *
//文 件 名:sja1000_pelican_ie.c *
//日 期:2007年8月16日 *
//***************************************************************************************************
//模拟 数据/地址总线 版
/*引用前需将以下外部定义包函进去
extern void sja1000_init(void); //SJA1000的初始化函数,初始化值在此函数中定义
extern INT8S can_data_write(INT8U *senddatabuf); //将待发送的数据(13个字节),写入SJA1000内部的发送缓存区中,然后启动SJA1000发送
extern INT8S can_data_receive(INT8U *rcvdatabuf); //将SJA1000内部接收缓冲器的13个字节的数据,存入微处理器保存接收数据的缓冲区(13个字节).
*/
/*
修改历史记录列表:
<修改日期> <修改内容简述>
2007/08/28 发送和接收 状态的查询 从查询 状态寄存器 改为查询 中断寄存器(因单片机自动复位) -- 没有效果,取消
//2007/09/29 增加 初始化 错误判定,由 symbol_CANInitError 判定
*/
//***************************************************************************************************
#include "sja1000.h"
//定义接收/发送缓冲区变量
CAN_BUFFER CAN_ReceiveBuffer;
CAN_BUFFER CAN_SendBuffer;
//***************************************************************************************************
//函数原型: void init_sja1000(void) *
//参数说明: 无 *
//返 回 值: 无 *
//说 明: CAN控制器的初始化函数。初始化操作之前请先将要初始化的各参数的值按数据手册中的计算方法, *
// 正确的按实际需要计算好参数后,将参数写入对应的寄存器 。 *
// 注 : 为了CAN控制器的正确运行,请务必仔细的阅读sja1000的数据手册 *
//***************************************************************************************************
void init_sja1000(void)
{
INT8U temp;
INT8U overtime_value = 200; //设置 超时值(10000us=10ms)
//****进入复位模式******************
temp = read_sja_reg(REG_MODE); //读出模式寄存器状态
while(((temp & Bit_RM) != Bit_RM) && overtime_value != 0) //在 成功进入复位模式 或 超时 后退出循环
{
write_sja_reg(REG_MODE,Bit_RM); //写模式寄存器,使之进入 复位;非睡眠;双验收滤波器;非自检测;非只听模式.
delay_us(50); //延时
overtime_value--;
temp = read_sja_reg(REG_MODE); //读出模式寄存器状态
}
if(overtime_value == 0) //进入复位模式 超时
{
#ifdef DEBUG //调试用
uart1_printf_ch("!!!!!!!! Enter Reset Mode OverTime ERR !!!!!!!!\n\r");
#endif
error(CAN_ENTRESET_ERR); //转到错误处理,SJA1000进入复位模式 超时 失败
}
//**** 设置 输出模式 , 时钟分频 ****
write_sja_reg(REG_OCR,0x1a); //正常输出模式,TX1悬空,TX0上拉
write_sja_reg(REG_CDR,0xc8); //PeliCAN 模式,时钟关闭,禁止TX1作为专用接收中断输出,禁止CAN输入比较器
//**** 设置 中断使能 ***************
// write_sja_reg(REG_IER,(Bit_RIE | Bit_TIE | Bit_DOIE)); //接收和发送中断使能,数据溢出中断使能位
write_sja_reg(REG_IER,0); //全部中断禁能
//**** 设置 验收代码和屏蔽 *********
write_sja_reg(REG_ACR0,0x01); //全部接收 , 不屏蔽
write_sja_reg(REG_ACR1,0x01);
write_sja_reg(REG_ACR2,0x01);
write_sja_reg(REG_ACR3,0x01);
write_sja_reg(REG_AMR0,0xff);
write_sja_reg(REG_AMR1,0xff);
write_sja_reg(REG_AMR2,0xff);
write_sja_reg(REG_AMR3,0xff);
//**** 设置 CAN总线波特率 ***********
write_sja_reg(REG_BTR0,0x87); //CAN总线波特率 = 50KBPS
write_sja_reg(REG_BTR1,0xdc);
//16M晶振下:0x93,0xdc(20KBPS);0x87,0xdc(50KBPS);0x83,0xdc(100KBPS);0x80,0x25(800KBPS)
//**** 初始化 CAN错误 寄存器 ********
write_sja_reg(REG_RXERR,0x00); //初始化 RX 错误计数寄存器
write_sja_reg(REG_TXERR,0x00); //初始化 TX 错误计数寄存器
write_sja_reg(REG_EWLR,96); //初始化 错误报警限制寄存器
//**** 退出复位模式 *****************
temp = read_sja_reg(REG_MODE); //读出模式寄存器状态
overtime_value = 200; //重置 超时值(10000us=10ms)
while(((temp & Bit_RM) == Bit_RM) && overtime_value != 0) //在 成功退出复位模式 或 超时 后退出循环
{
write_sja_reg(REG_MODE,(temp & (~Bit_RM))); //清除 复位模式请求位
delay_us(50); //延时
overtime_value--;
temp = read_sja_reg(REG_MODE); //读出模式寄存器状态
}
if(overtime_value == 0) //退出复位模式 超时
{
#ifdef DEBUG //调试用
uart1_printf_ch("\n\r\n\r!!!!!!!! Exit Reset Mode OverTime ERR !!!!!!!!\n\r");
#endif
error(CAN_QUITRESET_ERR); //转到错误处理,SJA1000退出复位模式 超时 失败
}
else
{
#ifdef DEBUG //调试用
uart1_printf_ch("\n\r\n\r!!!!!!!! Init SJA1000 OK !!!!!!!!\n\r");
#endif
}
}
//***************************************************************************************************
//函数原型: INT8S can_data_send(void) *
//参数说明: 无 *
//返 回 值: 0 ; 表示将数据(13个字节)写入SJA1000内部的发送缓冲区 成功 *
// -1 ; 表示发送缓冲区锁定,将数据(13个字节)写入SJA1000内部的发送缓冲区 失败 *
//说 明: 将待发送的数据(13个字节),写入SJA1000内部的发送缓存区中,然后启动SJA1000发送。 *
// 本函数的返回值仅指示,将数据写入SJA1000内部的发送缓存区并成功执行发送命令与否。 *
// 不指示SJA1000将该数据正确发送到CAN总线上完毕与否。 *
//***************************************************************************************************
INT8S can_data_send(void)
{
INT8U temp;
INT8U overtime_value = 250; //设置 超时值(2500us)
//状态判断
// temp = read_sja_reg(REG_INTERRUPT); //读出中断寄存器状态
// while(((temp & Bit_TI) == 0) && overtime_value != 0) //在 上次发送完成 或 超时 后退出循环
// {
// temp = read_sja_reg(REG_INTERRUPT); //读出中断寄存器状态
// delay_us(10);
// overtime_value--;
// }
//8.28 注释
temp = read_sja_reg(REG_STATUS); //读出状态寄存器状态
// if((temp & Bit_ES) != 0) //出错状态位 有效
// {
// init_sja1000(); //重新初始化SJA1000
//
// #ifdef DEBUG //调试用
// uart1_printf_ch("!!!!!!!!!!!!CAN Bit_ES in Error state!!!!!!!!!!!!\n\r");
// #endif
//
// error(CAN_COUNTERS_ERR); //转到错误处理,SJA1000 错误计数器 超限错误
// }
while(((temp & Bit_TCS) == 0) && overtime_value != 0) //在 上次发送完成 或 超时 后退出循环
{
temp = read_sja_reg(REG_STATUS); //读出状态寄存器状态
delay_us(10);
overtime_value--;
}
#ifdef DEBUG //调试用
if(overtime_value != 250)
{
uart1_printf_ch("CAN send wait ");
temp = (250 - overtime_value) * 10;
uart1_printf_num8(&temp);
uart1_printf_ch(" us!\n\r");
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -