这篇来学习下CAN1通信收到测试,开发板通过CAN1向外发送数据,开发板上的CAN1收到数据后。从串口输出接收到CAN信息。
一、硬件电路部分
1.1、CAN1收发器电路
1.2、CAN1通信MCU端口
CAN1使用MCU的PD4和PD5端口。
二、程序
2.1、can.c
#include "main.h"
#include "can.h"
uint8_t can1_rx_flag=0;
void CAN1_IrqCallback(void)
{
stc_can_error_info_t stcErr;
(void)CAN_GetErrorInfo(CAN1_UNIT, &stcErr);
// DDL_Printf("---> CAN error type: %u, %s\r\n", stcErr.u8ErrorType, m_s8ErrorTypeStr[stcErr.u8ErrorType]);
if (CAN_GetStatus(CM_CAN1, CAN_FLAG_BUS_OFF) == SET) {
DDL_Printf("BUS OFF.\r\n");
}
if (CAN_GetStatus(CM_CAN1, CAN_FLAG_RX_BUF_OVF) == SET) {
DDL_Printf("RX overflow.\r\n");
/* Call CAN_GetRxFrame() to get the received frame, then this flag cleared. */
}
if (CAN_GetStatus(CM_CAN1, CAN_FLAG_TX_BUF_FULL) == SET) {
DDL_Printf("TX buffer full.\r\n");
}
if (CAN_GetStatus(CAN1_UNIT, CAN_FLAG_TX_ABORTED) == SET) {
DDL_Printf("TX aborted.\r\n");
CAN_ClearStatus(CAN1_UNIT, CAN_FLAG_TX_ABORTED);
}
if (CAN_GetStatus(CM_CAN1, CAN_FLAG_STB_TX) == SET) {
//DDL_Printf("STB transmitted.\r\n");
CAN_ClearStatus(CM_CAN1, CAN_FLAG_STB_TX);
//m_u8STBTxFlag = 1U;
}
if (CAN_GetStatus(CM_CAN1, CAN_FLAG_PTB_TX) == SET) {
DDL_Printf("PTB transmitted.\r\n");
CAN_ClearStatus(CM_CAN1, CAN_FLAG_PTB_TX);
}
if (CAN_GetStatus(CM_CAN1, CAN_FLAG_RX) == SET) {
/* Received frame can be read here. */
//DDL_Printf("Received a frame.\r\n");
can1_rx_flag=1;
CAN_ClearStatus(CM_CAN1, CAN_FLAG_RX);
}
if (CAN_GetStatus(CM_CAN1, CAN_FLAG_RX_BUF_WARN) == SET) {
/* Received frames can be read here. */
DDL_Printf("RX buffer warning.\r\n");
//m_u8RxFlag = 1U;
CAN_ClearStatus(CM_CAN1, CAN_FLAG_RX_BUF_WARN);
}
if (CAN_GetStatus(CM_CAN1, CAN_FLAG_RX_BUF_FULL) == SET) {
/* Received frames can be read here. */
DDL_Printf("RX buffer full.\r\n");
//m_u8RxFlag = 1U;
CAN_ClearStatus(CM_CAN1, CAN_FLAG_RX_BUF_FULL);
}
if (CAN_GetStatus(CM_CAN1, CAN_FLAG_RX_OVERRUN) == SET) {
DDL_Printf("RX buffer overrun.\r\n");
//m_u8RxFlag = 1U;
CAN_ClearStatus(CM_CAN1, CAN_FLAG_RX_OVERRUN);
}
if (CAN_GetStatus(CM_CAN1, CAN_FLAG_TEC_REC_WARN) == SET) {
DDL_Printf("TEC or REC reached warning limit.\r\n");
}
}
void can1_txbuf(u32 id, u32 dlc, u8 *txbuf)
{
stc_can_tx_frame_t can1_tx1;
u8 i=0;
can1_tx1.u32Ctrl = 0x0UL;
can1_tx1.u32ID = id;
can1_tx1.IDE = 0U;
can1_tx1.DLC = dlc;
for(i=0;i<dlc;i++)
{
can1_tx1.au8Data[i] = txbuf[i];
}
CAN_FillTxFrame(CM_CAN1, CAN_TX_BUF_STB, &can1_tx1);
CAN_StartTx(CM_CAN1, CAN_TX_REQ_STB_ONE);
}
static void CanCommClockConfig(void)
{
CLK_SetCANClockSrc(CLK_CAN1, CLK_CANCLK_SYSCLK_DIV6);
}
static void CanPinConfig(void)
{
GPIO_SetFunc(GPIO_PORT_D, GPIO_PIN_05, GPIO_FUNC_60);
GPIO_SetFunc(GPIO_PORT_D, GPIO_PIN_04, GPIO_FUNC_61);
}
static void CanInitConfig(void)
{
stc_can_init_t stcCanInit;
stc_can_filter_config_t astcFilter[CAN_FILTER_NUM] = {
{CAN_FILTER1_ID, CAN_FILTER1_ID_MASK, CAN_FILTER1_ID_TYPE},
{CAN_FILTER2_ID, CAN_FILTER2_ID_MASK, CAN_FILTER2_ID_TYPE},
{CAN_FILTER3_ID, CAN_FILTER3_ID_MASK, CAN_FILTER3_ID_TYPE},
};
/* Initializes CAN. */
(void)CAN_StructInit(&stcCanInit);
stcCanInit.stcBitCfg.u32Prescaler = 2U;
stcCanInit.stcBitCfg.u32TimeSeg1 = 15U;
stcCanInit.stcBitCfg.u32TimeSeg2 = 5U;
stcCanInit.stcBitCfg.u32SJW = 5U;
stcCanInit.pstcFilter = astcFilter;
stcCanInit.u16FilterSelect = CAN_FILTER_SEL;
stcCanInit.u8WorkMode = CAN_WORK_MD_NORMAL;
/* Enable peripheral clock of CAN. */
FCG_Fcg1PeriphClockCmd(CAN1_PERIPH_CLK, ENABLE);
(void)CAN_Init(CAN1_UNIT, &stcCanInit);
/* Enable the interrupts, the status flags can be read. */
CAN_IntCmd(CAN1_UNIT, CAN_INT_ALL, DISABLE);
/* Enalbe the interrupts that needed. */
CAN_IntCmd(CAN1_UNIT, CAN_INT_SEL, ENABLE);
}
static void CanIrqConfig(void)
{
stc_irq_signin_config_t stcIrq;
stcIrq.enIntSrc = CAN1_INT_SRC;
stcIrq.enIRQn = CAN1_INT_IRQn;
stcIrq.pfnCallback = &CAN1_IrqCallback;
(void)INTC_IrqSignIn(&stcIrq);
NVIC_ClearPendingIRQ(stcIrq.enIRQn);
NVIC_SetPriority(stcIrq.enIRQn, CAN1_INT_PRIO);
NVIC_EnableIRQ(stcIrq.enIRQn);
}
static void CanPhyEnable(void)
{
BSP_IO_Init();
BSP_CAN_STB_IO_Init();
/* Set PYH STB pin as low. */
BSP_CAN_STBCmd(EIO_PIN_RESET);
}
void init_can(void)
{
CanCommClockConfig();
CanPinConfig();
CanInitConfig();
CanIrqConfig();
CanPhyEnable();
}
2.2、can.h
#ifndef _CAN_H
#define _CAN_H
#include "main.h"
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/* Unit definition of CAN in this example. */
#define CAN_SEL_UNIT1 (0U)
#define CAN_SEL_UNIT2 (1U)
/* Select a CAN unit. */
#define CAN_UNIT_SEL (CAN_SEL_UNIT1)
/* Definitions according to 'CAN_UNIT_SEL'. */
#if (CAN_UNIT_SEL == CAN_SEL_UNIT1)
#define CAN1_UNIT (CM_CAN1)
#define CAN1_PERIPH_CLK (FCG1_PERIPH_CAN1)
#define CAN1_TX_PORT (GPIO_PORT_D)
#define CAN1_TX_PIN (GPIO_PIN_05)
#define CAN1_TX_PIN_FUNC (GPIO_FUNC_60)
#define CAN1_RX_PORT (GPIO_PORT_D)
#define CAN1_RX_PIN (GPIO_PIN_04)
#define CAN1_RX_PIN_FUNC (GPIO_FUNC_61)
#define CAN1_CLK_UNIT (CLK_CAN1)
#define CAN1_CLK_SRC (CLK_CANCLK_SYSCLK_DIV6)
#define CAN1_INT_PRIO (DDL_IRQ_PRIO_03)
#define CAN1_INT_SRC (INT_SRC_CAN1_HOST)
#define CAN1_INT_IRQn (INT092_IRQn)
#elif (CAN_UNIT_SEL == CAN_SEL_UNIT2)
#define CAN_UNIT (CM_CAN2)
#define CAN_PERIPH_CLK (FCG1_PERIPH_CAN2)
#define CAN_TX_PORT (GPIO_PORT_D)
#define CAN_TX_PIN (GPIO_PIN_07)
#define CAN_TX_PIN_FUNC (GPIO_FUNC_62)
#define CAN_RX_PORT (GPIO_PORT_D)
#define CAN_RX_PIN (GPIO_PIN_06)
#define CAN_RX_PIN_FUNC (GPIO_FUNC_63)
#define CAN_CLK_UNIT (CLK_CAN2)
#define CAN_CLK_SRC (CLK_CANCLK_SYSCLK_DIV6)
#define CAN_INT_PRIO (DDL_IRQ_PRIO_03)
#define CAN_INT_SRC (INT_SRC_CAN2_HOST)
#define CAN_INT_IRQn (INT092_IRQn)
#else
#error "The unit is NOT supported!!!"
#endif
/* CAN interrupt type selection. */
#define CAN_INT_SEL (CAN_INT_STB_TX | \
CAN_INT_PTB_TX | \
CAN_INT_RX_BUF_WARN | \
CAN_INT_RX_BUF_FULL | \
CAN_INT_RX_OVERRUN | \
CAN_INT_RX)
/* Acceptance filter. */
#define CAN_FILTER_SEL (CAN_FILTER1 | CAN_FILTER2 | CAN_FILTER3)
#define CAN_FILTER_NUM (3U)
#define CAN_FILTER1_ID (0x701UL)
#define CAN_FILTER1_ID_MASK (0x0UL)
#define CAN_FILTER1_ID_TYPE (CAN_ID_STD) /*!< Only accept frames with standard ID 0x701. */
#define CAN_FILTER2_ID (0x12131415UL)
#define CAN_FILTER2_ID_MASK (0x000000F0UL)
#define CAN_FILTER2_ID_TYPE (CAN_ID_EXT) /*!< Accept frames with extended ID 0x121314x5. */
#define CAN_FILTER3_ID (0x1A1B1C1DUL)
#define CAN_FILTER3_ID_MASK (0x0000000FUL)
#define CAN_FILTER3_ID_TYPE (CAN_ID_STD_EXT) /*!< Accept frames with extended ID 0x1A1B1C1x, \
standard ID 0x41x(0x1A1B1C1D & 0x7FF(standard ID mask)). */
/* Message ID definitions. */
#define CAN_TX_ID1 (0x601UL)
#define CAN_TX_ID1_IDE (0U)
#define CAN_TX_ID2 (0x602UL)
#define CAN_TX_ID2_IDE (0U)
#define CAN_TX_ID3 (0x1020301UL)
#define CAN_TX_ID3_IDE (1U)
#define CAN_TX_ID4 (0x1030402UL)
#define CAN_TX_ID4_IDE (1U)
#define CAN_TX_ID5 (0x1030503UL)
#define CAN_TX_ID5_IDE (1U)
/* Size of the TX data. */
#define CAN_TX_DLC (CAN_DLC8)
#define CAN_TX_DATA_SIZE (8U)
/* Timeout value */
#define CAN_TX_TIMEOUT_MS (100U)
/* TX process */
#define CAN_TX_PROCESS_PTB (1U)
#define CAN_TX_PROCESS_STB (2U)
#define CAN_TX_PROCESS_PTB_STB (3U)
/* Number of RX frame */
#define CAN_RX_FRAME_NUM (8U)
extern uint8_t can1_rx_flag;
void init_can(void);
void can1_txbuf(u32 id, u32 dlc, u8 *txbuf);
void can1_rxbuf(stc_can_rx_frame_t rxbuf);
#endif
2.3、mian.c
#include "main.h"
#include "lcd.h"
#include "sram.h"
#include "timer0.h"
#include "led.h"
#include "touch.h"
#include "can.h"
stc_touchpad_data_t touchdat;
void SysTick_Handler(void)
{
SysTick_IncTick();
led1_tog();
}
int32_t main(void)
{
uint8_t can_txbuf[8];
stc_can_rx_frame_t can_rxbuf;
uint16_t u=0;
uint8_t i=0;
uint16_t cord[6]={WHITE, BLUE, BRED, GBLUE, RED, YELLOW};
/* Register write enable for some required peripherals. */
LL_PERIPH_WE(LL_PERIPH_GPIO | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_EFM | LL_PERIPH_SRAM);
BSP_CLK_Init();
/* EXCLK 60MHz */
CLK_SetClockDiv(CLK_BUS_EXCLK, CLK_EXCLK_DIV4);
DDL_PrintfInit(BSP_PRINTF_DEVICE, BSP_PRINTF_BAUDRATE, BSP_PRINTF_Preinit);
BSP_IO_Init();
BSP_LED_Init();
BSP_LCD_IO_Init();
init_led();
init_touch();
init_lcd();
init_sram();
init_timer0();
init_can();
SysTick_Init(1000U);
LL_PERIPH_WP(LL_PERIPH_GPIO | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_EFM | LL_PERIPH_SRAM);
POINT_COLOR=RED;
LCD_Clear(WHITE);
//sram_test();
for(u=0;u<8;u++)
{
can_txbuf[u]=0;
}
u=0;
for (;;)
{
TOUCHPAD_Read(&touchdat);
if (touchdat.enPointPress == SET)
{
DDL_Printf("x: %d, y: %d \r\n",touchdat.stcPoint.u16X,touchdat.stcPoint.u16Y );
}
BSP_LED_Toggle(LED_RED);
SysTick_Delay(500U);
BSP_LED_Toggle(LED_BLUE);
SysTick_Delay(500U);
u++;
if(u>250)
{
u=0;
}
can_txbuf[0]=u;
can_txbuf[1]=u+1;
can_txbuf[2]=u+2;
can_txbuf[3]=u+3;
can1_txbuf(0x301, CAN_DLC8, can_txbuf);
if(can1_rx_flag==1)
{
can1_rx_flag=0;
CAN_GetRxFrame(CM_CAN1, &can_rxbuf);
DDL_Printf("CAN received ID %.8x:\r\n", (unsigned int)can_rxbuf.u32ID);
for (i = 0; i < (uint8_t)can_rxbuf.DLC; i++)
{
DDL_Printf(" %.2x.", can_rxbuf.au8Data[i]);
can_rxbuf.au8Data[i] = 0U;
}
DDL_Printf("\r\n");
}
}
}
三、程序运行
串口收到的数据和CAN软件收发的数据
|