前几章都已经知道了keil的调试流程和芯片的基本参数了,那么这一次就可以直接来编写一些测试的DEMO小程序,那就直接在官方例程上面来实现吧
选择官方的CAN_ClassicFrames例程,打开里面可以知道通过两个按键来发送CAN,分别是扩展帧和标准帧格式,那么这也就是经典的CAN2.0B。
那我直接给工程做一些小小的改动,首先要有自己的思路,板子供电,切换5V给MCU,连接CANH 和CANL到CAN工具上,CAN的两端最好都要加上终端电阻120欧,测试50ms循环发送CAN报文,并且根据收到指定报文的信号来决定亮什么颜色的灯。
思路有了之后,就开始实践,1.时钟初始化,2.引脚初始化。3.can 外设初始化 。(发送邮箱,接收邮箱,将过滤ID,安装中断服务函数,调用接收函数)4.CAN中断里面编写接收处理
代码如下:
/*!
* @file main.c
*
* @brief Main program
*
* @version V1.0.0
*
* @date 2024-03-20
*
* @attention
*
* Copyright (C) 2024 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "user_config.h"
#include "board.h"
/** @addtogroup G32A1465_Examples
@{
*/
/** @addtogroup CAN_ClassicFrames
@{
*/
/** @defgroup CAN_ClassicFrames_Macros Macros
@{
*/
/* CAN instance */
#define CAN0_INSTANCE (0U)
/* MB0 is used to receive standard CAN frames */
#define RX_MB_0 (0U)
/* MB1 is used to receive extended CAN frames */
#define RX_MB_1 (1U)
/* The MB used to transmit CAN frames */
#define TX_MB (2U)
/* CAN message IDs */
#define RX_CAN_MESSAGE_ID (0x303U)
#define TX_CAN_MESSAGE_ID_1 (0x404U)
#define TX_CAN_MESSAGE_ID_2 (0x505U)
CAN_MSG_BUF_T rxFrame0;
CAN_MSG_BUF_T rxFrame1;
uint8_t payload[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
CAN_DATA_INFO_T txDataInfo = {
.msgIdType = CAN_ID_STANDARD, /* Standard CAN ID */
.dataLen = sizeof(payload), /* Payload size */
.fdEnable = false,
.isRemote = false
};
/**@} end of group CAN_ClassicFrames_Macros*/
/** @defgroup CAN_ClassicFrames_Variables Variables
@{
*/
/* Indicate MB0 receive is completed */
volatile bool g_mb0ReceiveCompleted = false;
/* Indicate MB1 receive is completed */
volatile bool g_mb1ReceiveCompleted = false;
/**@} end of group CAN_ClassicFrames_Variables*/
/** @defgroup CAN_ClassicFrames_Functions Functions
@{
*/
/*!
* @brief This function is called when a CAN event occurred
*/
void CanEventCallback(
uint8_t instance,
CAN_EVENT_TYPE_T eventType,
uint32_t mbIndex,
CAN_STATE_T *driverState)
{
/* A frame was received in the configured Rx MB */
if (eventType == CAN_EVENT_RX_COMPLETE)
{
/* Set the receive complete flags */
if (mbIndex == RX_MB_0)
{
CAN_ReceiveNonBlocking(CAN0_INSTANCE, RX_MB_0, &rxFrame0);
g_mb0ReceiveCompleted = 1;
}
if (mbIndex == RX_MB_1)
{
CAN_ReceiveNonBlocking(CAN0_INSTANCE, RX_MB_1, &rxFrame1);
}
}
}
/*!
* @brief This function is called when the KEY1 button is pressed
*/
void Key1Handler(void)
{
/* Send standard CAN frame */
uint8_t payload[6] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35};
CAN_DATA_INFO_T txDataInfo = {
.msgIdType = CAN_ID_STANDARD, /* Standard CAN ID */
.dataLen = sizeof(payload), /* Payload size */
.fdEnable = false,
.isRemote = false
};
CAN_SendNonBlocking(CAN0_INSTANCE, TX_MB, &txDataInfo, TX_CAN_MESSAGE_ID_1, payload);
}
/*!
* @brief This function is called when the KEY2 button is pressed
*/
void Key2Handler(void)
{
/* Send extended CAN frame */
uint8_t payload[7] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36};
CAN_DATA_INFO_T txDataInfo = {
.msgIdType = CAN_ID_EXTENDED, /* Extended CAN ID */
.dataLen = sizeof(payload), /* Payload size */
.fdEnable = false,
.isRemote = false
};
CAN_SendNonBlocking(CAN0_INSTANCE, TX_MB, &txDataInfo, TX_CAN_MESSAGE_ID_2, payload);
}
/*!
* @brief Main function
* @param None
* @retval Exit code
*/
int main(void)
{
bool exit = false;
CAN_STATE_T canState;
CAN_TIME_SEGMENT_T canBitrate;
/* Initialize clock */
CLOCK_SYS_Init(&g_clockConfig);
/* Initialize pins */
PINS_Init(NUM_OF_CONFIGURED_PINS0, g_pinsConfig);
/* Initialize LEDs */
LED_Init();
// LED_On(LED_GREEN);
/* Initialize buttons */
BTN_Init();
BTN_InstallKey1Handler(Key1Handler);
BTN_InstallKey2Handler(Key2Handler);
/* Initialize the CAN controller, bitrate is 250K */
CAN_Init(CAN0_INSTANCE, &canState, &g_canConfig);
/* Get the current CAN bitrate */
CAN_GetBitrate(CAN0_INSTANCE, &canBitrate);
/* Configure Tx MB */
CAN_DATA_INFO_T txMbInfo = {
.msgIdType = CAN_ID_STANDARD, /* Standard CAN ID */
.dataLen = 8, /* Used only to initialize the MB, will be updated when send data */
.fdEnable = false, /* Disable CAN FD */
.isRemote = false
};
CAN_ConfigureTxMb(CAN0_INSTANCE, TX_MB, &txMbInfo, 0);
/* Use individual Rx masking for the MBs */
CAN_SetRxMaskType(CAN0_INSTANCE, CAN_RX_MASK_INDIVIDUAL);
/* Configure Rx MB0, it will receive standard frames with ID 1 */
CAN_DATA_INFO_T rxMb0Info = {
.msgIdType = CAN_ID_STANDARD, /* Standard CAN ID */
.dataLen = 8, /* Max data length for classic CAN is 8 bytes */
.fdEnable = false, /* Disable CAN FD */
.isRemote = false
};
CAN_ConfigureRxMb(CAN0_INSTANCE, RX_MB_0, &rxMb0Info, RX_CAN_MESSAGE_ID);
CAN_SetRxIndividualMask(CAN0_INSTANCE, CAN_ID_STANDARD, RX_MB_0, 0x0);
/* Configure Rx MB1, it will receive extended frames with ID 1 */
CAN_DATA_INFO_T rxMb1Info = {
.msgIdType = CAN_ID_EXTENDED, /* Extended CAN ID */
.dataLen = 8, /* Max data length for classic CAN is 8 bytes */
.fdEnable = false, /* Disable CAN FD */
.isRemote = false
};
CAN_ConfigureRxMb(CAN0_INSTANCE, RX_MB_1, &rxMb1Info, RX_CAN_MESSAGE_ID);
CAN_SetRxIndividualMask(CAN0_INSTANCE, CAN_ID_EXTENDED, RX_MB_1, 0xFFFFFFFF);
/* Set the CAN event callback handler */
CAN_InstallEventCallback(CAN0_INSTANCE, &CanEventCallback, NULL);
/* Receive CAN frames from MB0 and MB1 */
CAN_ReceiveNonBlocking(CAN0_INSTANCE, RX_MB_0, &rxFrame0);
while (!exit)
{
OSIF_TimeDelay(50);
CAN_SendNonBlocking(CAN0_INSTANCE, TX_MB, &txDataInfo, TX_CAN_MESSAGE_ID_1, payload);
if(g_mb0ReceiveCompleted == 1)
{
if(rxFrame0.data[0] == 0)
{
LED_On(LED_RED);
LED_Off(LED_GREEN);
LED_Off(LED_BLUE);
}
else if(rxFrame0.data[0] == 1)
{
LED_On(LED_GREEN);
LED_Off(LED_RED);
LED_Off(LED_BLUE);
}
else if(rxFrame0.data[0] == 2)
{
LED_On(LED_BLUE);
LED_Off(LED_RED);
LED_Off(LED_GREEN);
}
else
{
LED_Off(LED_RED);
LED_Off(LED_BLUE);
LED_Off(LED_GREEN);
}
}
}
CAN_DeInit(CAN0_INSTANCE);
LED_On(LED_RED);
return 0;
}
/**@} end of group CAN_ClassicFrames_Functions */
/**@} end of group CAN_ClassicFrames */
/**@} end of group Examples */
这样我就实现了收到报文ID303的第一位数据变化灯的颜色了,实测也是没有问题。
不过最后其实有一点想说的,不知道极海有没有可以像s32dsV2.2 开发工具那样,直接对需要的外设和引脚进行图形化配置,最后直接生成出相应的代码。如果有的话,那么可以节省很大一部分时间来减少开发的工作量。
在此也感谢极海能够提供这一次的测评机会,后面我也会把自己遇到的一些问题分享给大家。希望大家多多交流!
|
|