测试一个ES32F0654的CAN接口功能,硬件需要一个CAN调试器,ES32F0654板上需要增加一个CAN接口芯片,如TJA1050.淘宝上有这样的小板卖。
软件配置如下:
#ifndef __CAN__H
#define __CAN__H
#define CAN_GpioInit() do{ \
GPIO_Init(GPIOA, GPIO_PIN_12, 1, IO_OUT_PP); \
GPIO_Init(GPIOA, GPIO_PIN_11, 1, IO_IN_PU); \
GPIO_SetAfMode(GPIOA, GPIO_PIN_12, GPIO_FUNC_4); \
GPIO_SetAfMode(GPIOA, GPIO_PIN_11, GPIO_FUNC_4); \
}while(0)
//波特率为500K,计算方法为:PCLK/(psc)/((sjw+1)+(seg1+1)+(seg2+1)) = 48M/(8)/((0+1)+(6+1)+(3+1))=500K
#define CAN_ModuleInit() do{ \
can_init_t init_str; \
can_filter_t filt_str; \
can_reset(CAN0); \
init_str.psc = 8; \
init_str.mode = CAN_MODE_NORMAL; \
init_str.sjw = CAN_SJW_1; \
init_str.seg1 = CAN_SEG1_7; \
init_str.seg2 = CAN_SEG2_4; \
init_str.ttcm = DISABLE; \
init_str.abom = DISABLE; \
init_str.awk = DISABLE; \
init_str.artx = ENABLE; \
init_str.rfom = DISABLE; \
init_str.txmp = DISABLE; \
can_init(CAN0, &init_str); \
filt_str.scale = CAN_FILTER_SCALE_32; \
filt_str.mode = CAN_FILTER_MODE_MASK; \
filt_str.fifo = CAN_FILTER_FIFO0; \
filt_str.id_low = 0; \
filt_str.id_high = 0; \
filt_str.mask_id_low = 0, \
filt_str.mask_id_high = 0, \
filt_str.number = 0; \
filt_str.bank_number = 0; \
filt_str.active = ENABLE; \
can_filter_config(CAN0, &filt_str); \
}while(0)
#define CAN_BUFF_SIZE 10
typedef struct{
can_tx_msg_t tx_msg[CAN_BUFF_SIZE];
can_rx_msg_t rx_msg[CAN_BUFF_SIZE];
INT8U TxCnt;
INT8U RxCnt;
}CAN_Str;
extern CAN_Str CAN_Info;
extern INT8U CAN_Test[];
extern void CAN_Init(void);
extern INT8U CAN_SendMsg(can_id_type_t id_type, uint32_t id_ext, can_remote_req_t rtr, INT8U *ptr, INT8U Len);
extern INT8U CAN_RecvieMsg(void);
#endif
收发程序:
//CAN发送
INT8U CAN_SendMsg(can_id_type_t id_type, uint32_t id, can_remote_req_t rtr, INT8U *ptr, INT8U Len)
{
while(Len > 0)
{
if(CAN_Info.TxCnt >= CAN_BUFF_SIZE) break;
CAN_Info.tx_msg[CAN_Info.TxCnt].type = id_type;
if(id_type == CAN_ID_STD)
{
CAN_Info.tx_msg[CAN_Info.TxCnt].std = id;
}
else
{
CAN_Info.tx_msg[CAN_Info.TxCnt].ext = id;
}
CAN_Info.tx_msg[CAN_Info.TxCnt].rtr = rtr;
if(Len >= 8)
{
MEM_Copy(ptr, (CAN_Info.tx_msg[CAN_Info.TxCnt].data), 8);
ptr += 8;
Len -= 8;
CAN_Info.tx_msg[CAN_Info.TxCnt].len = 8;
}
else
{
MEM_Copy(ptr, (CAN_Info.tx_msg[CAN_Info.TxCnt].data), Len);
CAN_Info.tx_msg[CAN_Info.TxCnt].len = Len;
Len = 0;
}
CAN_Info.TxCnt++;
}
if(CAN_Info.TxCnt > 0)
{
CAN_Info.TxCnt--;
can_send(CAN0, &(CAN_Info.tx_msg[CAN_Info.TxCnt]), 100);
}
return(1);
}
//CAN接收
INT8U CAN_RecvieMsg(void)
{
if(can_recv(CAN0, CAN_RX_FIFO0, &(CAN_Info.rx_msg[CAN_Info.RxCnt]), 100) != OK)
{
return(0);
}
//收到8个字节的数据,扩展帧的ID是0x1234,把8个字节的数据写到发送缓冲区,
if((CAN_Info.rx_msg[CAN_Info.RxCnt].len != 0) && (CAN_Info.rx_msg[CAN_Info.RxCnt].ext == 0x1234))
{
MEM_Copy(CAN_Info.rx_msg[CAN_Info.RxCnt].data, CAN_Test, 8);
}
else
{
return(0);
}
return(1);
}
//CAN中断
void CAN0_Handler(void)
{
can_irq_handler(CAN0);
}
主函数中加个任务:
TASK_TYPE TASK_Can(void)
{
TASK_Start();
CAN_SendMsg(CAN_ID_EXT, 0x1234, CAN_RTR_DATA, CAN_Test, 8);
CAN_RecvieMsg();
TASK_WaitX(11); //等待11ms
TASK_End();
}
cantest 设置只修改一下波特率为500K,其他保持默认就行
程序 上电后默认发送“ES32F056”的十六进制数,
在cantest软件里修改一下发送配置,修改为扩展 帧,帧ID为0x1234,发送数据就随意了,是8个字节就行了,修改完后点发送,ES32F0654发送上来的数据就修改为了刚刚发送过去的数据。
附CAN测试HEX文件:
es32f065xdemo_can.rar
(12.19 KB)
|