stm32-code/stm32f103_can/Core/Src/app_main.c

198 lines
5.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "app_main.h"
#include <stdio.h>
#include <string.h>
// 地址 ID高3位 0x0-0x7
#define CAN_ADDRESS_HOST 0x7
#define CAN_ADDRESS_DEVICE 0x1
#define CAN_ADDRESS_MASK 0x7
// 指令 ID低8位 0x00-0xFF
#define CAN_COMMAND_LED_CONTROL 0x01
#define CAN_COMMAND_LED_STATUS 0x02
#define CAN_COMMAND_MASK 0xFF
static volatile uint8_t led_status[2] = { 0 };
static volatile uint8_t led_status_changed = 0;
void can_configure(void)
{
/**
* BYTE3 | BYTE2 | BYTE1 | BYTE0
* STID[10:3] | STID[2:0] EXID[17:13] | EXID[12:5] | EXID[4:0] IDE RTR 0
*
* STID[10:4] 标准ID此处用作地址Id置CAN_ADDRESS_HOST的值MaskId置0x7F
* EXID[17:15] 扩展ID未使用Id置全0Mask置全0
* RTR 1为遥控帧0为数据帧此处均接收不需要过滤Id任意MaskId置0
* IDE 1为扩展ID格式0为标准ID格式此处只接收标准格式需要过滤Id置0MaskId置1
*/
uint32_t filter_id = ((uint32_t)CAN_ADDRESS_DEVICE << 8) << 21;
uint32_t filter_id_mask = (((uint32_t)CAN_ADDRESS_MASK << 8) << 21) | ((uint32_t)0x01 << 3);
CAN_FilterTypeDef filter;
filter.FilterBank = 0;
filter.FilterMode = CAN_FILTERMODE_IDMASK; //过滤除主机发送的所有帧
filter.FilterScale = CAN_FILTERSCALE_32BIT; //标准ID格式Id与Mask的High与Low分别代表两个过滤器
filter.FilterIdHigh = filter_id >> 16;
filter.FilterIdLow = (uint16_t)filter_id;
filter.FilterMaskIdHigh = filter_id_mask >> 16;
filter.FilterMaskIdLow = (uint16_t)filter_id_mask;
filter.FilterFIFOAssignment = CAN_RX_FIFO0;
filter.FilterActivation = ENABLE;
HAL_CAN_ConfigFilter(&hcan, &filter); //配置接收过滤器
HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_TX_MAILBOX_EMPTY | CAN_IT_ERROR); //使能接收与发送中断
HAL_CAN_ActivateNotification(&hcan, CAN_IT_ERROR | CAN_IT_RX_FIFO0_OVERRUN | CAN_IT_RX_FIFO0_FULL | CAN_IT_LAST_ERROR_CODE); //使能错误中断
HAL_CAN_Start(&hcan); //使能CAN外设
}
HAL_StatusTypeDef can_transmit(uint16_t id, const uint8_t *data, uint8_t length)
{
CAN_TxHeaderTypeDef header = {
.IDE = CAN_ID_STD, //标准ID格式
.RTR = CAN_RTR_DATA, //数据帧
.StdId = id,
.DLC = length
};
uint32_t mailbox;
return HAL_CAN_AddTxMessage(&hcan, &header, data, &mailbox);
}
void app_led_update(void)
{
if (led_status[0]) {
LED1_ON();
} else {
LED1_OFF();
}
if (led_status[1]) {
LED2_ON();
} else {
LED2_OFF();
}
}
void app_key_process(void)
{
if (KEY1_PRESSED()) {
led_status[0] = !led_status[0];
led_status_changed = 1;
HAL_Delay(100);
while (KEY1_PRESSED());
HAL_Delay(100);
}
if (KEY2_PRESSED()) {
led_status[1] = !led_status[1];
led_status_changed = 1;
HAL_Delay(100);
while (KEY2_PRESSED());
HAL_Delay(100);
}
}
void app_can_update(void)
{
if (led_status_changed) {
can_transmit((CAN_ADDRESS_HOST << 8) | CAN_COMMAND_LED_STATUS, (uint8_t*)led_status, sizeof(led_status));
led_status_changed = 0;
}
}
void app_main(void)
{
can_configure();
while (1) {
app_key_process();
app_led_update();
app_can_update();
}
}
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
CAN_RxHeaderTypeDef header;
uint8_t data[8];
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &header, data) != HAL_OK || header.DLC < 2) {
printf("wrong can message\r\n");
return;
}
if ((header.StdId & 0xFF) == CAN_COMMAND_LED_CONTROL) {
if (data[0] == 1) { //点亮
led_status[0] = 1;
} else if (data[0] == 2) { //熄灭
led_status[0] = 0;
} else if (data[0] == 3) { //切换
led_status[0] = !led_status[0];
}
if (data[1] == 1) { //点亮
led_status[1] = 1;
} else if (data[1] == 2) { //熄灭
led_status[1] = 0;
} else if (data[1] == 3) { //切换
led_status[1] = !led_status[1];
}
led_status_changed = 1;
} else {
printf("unhandled command: 0x%02X\r\n", (int)header.StdId & 0xFF);
}
}
void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan)
{
printf("rx fifo full!\r\n");
}
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan)
{
printf("tx mailbox0 send ok\r\n");
}
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan)
{
printf("tx mailbox1 send ok\r\n");
}
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan)
{
printf("tx mailbox2 send ok\r\n");
}
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
{
uint32_t error_code = HAL_CAN_GetError(hcan);
if (error_code & (HAL_CAN_ERROR_RX_FOV0 | HAL_CAN_ERROR_RX_FOV1)) {
printf("rx fifo overrun error");
}
if (error_code & (HAL_CAN_ERROR_TX_ALST0 | HAL_CAN_ERROR_TX_ALST1 | HAL_CAN_ERROR_TX_ALST2)) {
printf("tx mailbox arbitration failure"); //仲裁失败导致的发送错误
} else if (error_code & (HAL_CAN_ERROR_TX_TERR0 | HAL_CAN_ERROR_TX_TERR1 | HAL_CAN_ERROR_TX_TERR2)) {
printf("tx mailbox transmit error"); //发送失败导致的发送错误
}
if (error_code & HAL_CAN_ERROR_STF) {
printf(", reason: stuff error"); //位填充错误
} else if (error_code & HAL_CAN_ERROR_FOR) {
printf(", reason: form error"); //格式错误
} else if (error_code & HAL_CAN_ERROR_ACK) {
printf(", reason: acknowledgment error"); //ACK错误
} else if (error_code & HAL_CAN_ERROR_BR) {
printf(", reason: bit recessive error"); //显性位错误
} else if (error_code & HAL_CAN_ERROR_BD) {
printf(", reason: bit dominant error"); //隐性位错误
} else if (error_code & HAL_CAN_ERROR_CRC) {
printf(", reason: crc error"); //CRC校验错误
}
printf("\r\n");
}