实现基于freeRTOS下的CAN通信。
一、freeRTOS移植
1.1、freeRTOS源码下载
官网地址:https://www.freertos.org/
github下载地址:https://github.com/FreeRTOS/FreeRTOS
1.2、复制文件
在工程项目下创建freeRTOS文件夹,将下载的freeRTOS源码复制到此文件夹下
替换后
1.3、添加文件到项目
1.4、修改配置文件
freeRTOSConfig.h
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#include "sys.h"
#include "usart.h"
#ifdef __ICCARM__
#include <stdint.h>
extern uint32_t SystemCoreClock;
#endif
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 32 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 20 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MALLOC_FAILED_HOOK 0
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES-1 )
#define configTIMER_QUEUE_LENGTH 5
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#ifdef __NVIC_PRIO_BITS
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4
#endif
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#endif
二、测试线程
上面的工程创建后,创建线程测试下
2.1、创建两个打印线程
#include "main.h"
#include <stdio.h>
#include <stdint.h>
#include "led.h"
#include "delay.h"
#include "st7789.h"
#include "FreeRTOS.h"
#include "usart.h"
#include "task.h"
#define START_TASK_PRIO 1
#define START_STK_SIZE 128
TaskHandle_t StartTask_Handler;
void start_task(void *pvParameters);
#define TASK1_TASK_PRIO 2
#define TASK1_STK_SIZE 128
TaskHandle_t Task1Task_Handler;
void task1_task(void *pvParameters);
#define TASK2_TASK_PRIO 3
#define TASK2_STK_SIZE 128
TaskHandle_t Task2Task_Handler;
void task2_task(void *pvParameters);
int main(void)
{
delay_init();
uart_init(115200);
LED_Init();
xTaskCreate((TaskFunction_t )start_task,
(const char* )"start_task",
(uint16_t )START_STK_SIZE,
(void* )NULL,
(UBaseType_t )START_TASK_PRIO,
(TaskHandle_t* )&StartTask_Handler);
vTaskStartScheduler();
}
void start_task(void *pvParameters)
{
taskENTER_CRITICAL();
xTaskCreate((TaskFunction_t )task1_task,
(const char* )"task1_task",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_TASK_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
xTaskCreate((TaskFunction_t )task2_task,
(const char* )"task2_task",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_TASK_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
vTaskDelete(StartTask_Handler);
taskEXIT_CRITICAL();
}
void task1_task(void *pvParameters)
{
while(1)
{
printf("task1 running... !\r\n");
vTaskDelay(1000);
}
}
void task2_task(void *pvParameters)
{
while(1)
{
printf("task2 running... !\r\n");
vTaskDelay(200);
}
}
2.2、串口输出
上面的工程创建完成。
三、添加CAN通信
3.1、CAN驱动程序
can.c
#include "n32g45x.h"
#include "can.h"
uint8_t CAN_Tx_Index=0;
CanTxMessage CAN_TxMessage;
CanTxMessage CAN_TxMessages[CAN_TX_MESSAGE_BUFF_SIZE];
CanRxMessage CAN_RxMessage[CAN_RX_MESSAGE_BUFF_SIZE];
uint8_t CAN_RxMessage_Write_Cursor=0;
uint8_t CAN_RxMessage_Read_Cursor=0;
void CAN_Filter_Init(void)
{
CAN_FilterInitType CAN_FilterInitStructure;
CAN_FilterInitStructure.Filter_Num = CAN_FILTERNUM0;
CAN_FilterInitStructure.Filter_Mode = CAN_Filter_IdMaskMode;
CAN_FilterInitStructure.Filter_Scale = CAN_Filter_32bitScale;
CAN_FilterInitStructure.Filter_HighId = CAN_FILTER_STDID(0x400);
CAN_FilterInitStructure.Filter_LowId = CAN_FILTER_STDID(0x400);
CAN_FilterInitStructure.FilterMask_HighId = CAN_STD_ID_H_MASK_DONT_CARE;
CAN_FilterInitStructure.FilterMask_LowId = CAN_STD_ID_L_MASK_DONT_CARE;
CAN_FilterInitStructure.Filter_FIFOAssignment = CAN_FIFO0;
CAN_FilterInitStructure.Filter_Act = ENABLE;
CAN1_InitFilter(&CAN_FilterInitStructure);
CAN_INTConfig(CAN1, CAN_INT_FMP0, ENABLE);
}
void CAN_NVIC_Config(void)
{
NVIC_InitType NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
uint8_t CANTxMessage(CAN_Module* CANx,CanTxMessage* TxMessage)
{
return CAN_TransmitMessage(CANx, TxMessage);
}
void Tx_Frame_Message_Init(void)
{
uint8_t CAN_Tx_Frame1_Data[8]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
uint8_t CAN_Tx_Frame2_Data[8]={0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01};
uint8_t i = 0;
CAN_TxMessages[0].StdId = CAN_TX1_SID;
CAN_TxMessages[0].IDE = CAN_ID_STD;
CAN_TxMessages[0].RTR = CAN_RTRQ_DATA;
CAN_TxMessages[0].DLC = CAN_TXDLC_8;
for(i=0;i<CAN_TXDLC_8;i++)
{
CAN_TxMessages[0].Data[i]=CAN_Tx_Frame1_Data[i];
}
CAN_TxMessages[1].ExtId = CAN_TX2_EID;
CAN_TxMessages[1].IDE = CAN_ID_EXT;
CAN_TxMessages[1].RTR = CAN_RTRQ_DATA;
CAN_TxMessages[1].DLC = CAN_TXDLC_8;
for(i=0;i<CAN_TXDLC_8;i++)
{
CAN_TxMessages[1].Data[i]=CAN_Tx_Frame2_Data[i];
}
}
void CAN_Recieve_Process(void)
{
uint8_t i=0;
if(CAN_RxMessage_Write_Cursor!=CAN_RxMessage_Read_Cursor)
{
if(CAN_RxMessage[CAN_RxMessage_Read_Cursor].IDE==CAN_Extended_Id)
{
printf("\r\n Receive Frame:%X %X ",\
CAN_RxMessage[CAN_RxMessage_Read_Cursor].ExtId,\
CAN_RxMessage[CAN_RxMessage_Read_Cursor].DLC);
}
else
{
printf("\r\n Receive Frame:%X %X ",\
CAN_RxMessage[CAN_RxMessage_Read_Cursor].StdId,\
CAN_RxMessage[CAN_RxMessage_Read_Cursor].DLC);
}
for(i=0;i<8;i++)
printf(" %X",CAN_RxMessage[CAN_RxMessage_Read_Cursor].Data[i]);
printf("\r\n");
if(CAN_RxMessage_Read_Cursor++>=CAN_RX_MESSAGE_BUFF_SIZE)CAN_RxMessage_Read_Cursor=0;
}
}
void can_txdat(uint8_t *dat)
{
uint8_t i=0;
for(i=0;i<8;i++)
{
CAN_TxMessages[0].Data[i]=dat[i];
}
CANTxMessage(CAN1,&CAN_TxMessages[0]);
}
void init_can(void)
{
CAN_InitType CAN_InitStructure;
GPIO_InitType GPIO_InitStructure;
GPIO_InitStruct(&GPIO_InitStructure);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO | RCC_APB2_PERIPH_GPIOB, ENABLE);
GPIO_InitStructure.Pin = GPIO_PIN_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
GPIO_ConfigPinRemap(GPIO_RMP2_CAN1, ENABLE);
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_CAN1, ENABLE);
CAN_DeInit(CAN1);
CAN_InitStruct(&CAN_InitStructure);
CAN_InitStructure.TTCM = DISABLE;
CAN_InitStructure.ABOM = DISABLE;
CAN_InitStructure.AWKUM = DISABLE;
CAN_InitStructure.NART = DISABLE;
CAN_InitStructure.RFLM = DISABLE;
CAN_InitStructure.TXFP = ENABLE;
CAN_InitStructure.OperatingMode = OPERATINGMODE;
CAN_InitStructure.RSJW = CAN_BIT_RSJW;
CAN_InitStructure.TBS1 = CAN_BIT_BS1;
CAN_InitStructure.TBS2 = CAN_BIT_BS2;
CAN_InitStructure.BaudRatePrescaler = CAN_BAUDRATEPRESCALER;
CAN_Init(CAN1, &CAN_InitStructure);
CAN_Filter_Init();
CAN_NVIC_Config();
Tx_Frame_Message_Init();
}
can.h
#ifndef __CAN_H__
#define __CAN_H__
#ifdef __cplusplus
extern "C" {
#endif
#define CAN_MODE_TYPE_NORMAL 1
#define CAN_MODE_TYPE_LOOPBACK 2
#define CAN_MODE_TYPE_SILENT 3
#define CAN_MODE_TYPE_SILENT_LOOPBACK 4
#define CAN_MODE_TYPE CAN_MODE_TYPE_NORMAL
#if(CAN_MODE_TYPE==CAN_MODE_TYPE_NORMAL)
#define OPERATINGMODE CAN_Normal_Mode
#elif(CAN_MODE_TYPE==CAN_MODE_TYPE_LOOPBACK)
#define OPERATINGMODE CAN_LoopBack_Mode
#elif(CAN_MODE_TYPE==CAN_MODE_TYPE_SILENT)
#define OPERATINGMODE CAN_Silent_Mode
#elif(CAN_MODE_TYPE==CAN_MODE_TYPE_SILENT_LOOPBACK)
#define OPERATINGMODE CAN_Silent_LoopBack_Mode
#endif
#define CAN_BAUDRATE_1M 1
#define CAN_BAUDRATE_500K 2
#define CAN_BAUDRATE_250K 3
#define CAN_BAUDRATE_125K 4
#define CAN_BAUDRATE CAN_BAUDRATE_500K
#if(CAN_BAUDRATE==CAN_BAUDRATE_1M)
#define CAN_BIT_RSJW CAN_RSJW_1tq
#define CAN_BIT_BS1 CAN_TBS1_5tq
#define CAN_BIT_BS2 CAN_TBS2_3tq
#define CAN_BAUDRATEPRESCALER 4
#elif(CAN_BAUDRATE==CAN_BAUDRATE_500K)
#define CAN_BIT_RSJW CAN_RSJW_1tq
#define CAN_BIT_BS1 CAN_TBS1_14tq
#define CAN_BIT_BS2 CAN_TBS2_3tq
#define CAN_BAUDRATEPRESCALER 4
#elif(CAN_BAUDRATE==CAN_BAUDRATE_250K)
#define CAN_BIT_RSJW CAN_RSJW_1tq
#define CAN_BIT_BS1 CAN_TBS1_14tq
#define CAN_BIT_BS2 CAN_TBS2_3tq
#define CAN_BAUDRATEPRESCALER 8
#elif(CAN_BAUDRATE==CAN_BAUDRATE_125K)
#define CAN_BIT_RSJW CAN_RSJW_2tq
#define CAN_BIT_BS1 CAN_TBS1_13tq
#define CAN_BIT_BS2 CAN_TBS2_4tq
#define CAN_BAUDRATEPRESCALER 16
#endif
#define CAN_TXDLC_8 ((uint8_t)8)
#define CAN_FILTERNUM0 ((uint8_t)0)
#define CAN_TX1_SID 0x0400
#define CAN_TX2_EID 0x12345678
#define CAN_TX_MESSAGE_BUFF_SIZE 2
#define CAN_RX_MESSAGE_BUFF_SIZE 10
#define CAN_FILTER_STDID(STDID) ((STDID&0x7FF)<<5)
#define CAN_FILTER_EXTID_H(EXTID) ((uint16_t)(((EXTID>>18)<<5)|((EXTID&0x2FFFF)>>13)))
#define CAN_FILTER_EXTID_L(EXTID) ((uint16_t)((EXTID&0x2FFFF)<<3))
#define CAN_STD_ID_H_MASK_CARE 0xFFE0
#define CAN_STD_ID_L_MASK_CARE 0x0000
#define CAN_STD_ID_H_MASK_DONT_CARE 0x0000
#define CAN_STD_ID_L_MASK_DONT_CARE 0x0000
#define CAN_EXT_ID_H_MASK_CARE 0xFFFF
#define CAN_EXT_ID_L_MASK_CARE 0xFFF8
#define CAN_EXT_ID_H_MASK_DONT_CARE 0x0000
#define CAN_EXT_ID_L_MASK_DONT_CARE 0x0000
typedef enum
{
FAILED = 0,
PASSED = !FAILED
} Status;
extern uint8_t CAN_Tx_Index;
extern uint8_t CAN_RxMessage_Write_Cursor;
extern uint8_t CAN_RxMessage_Read_Cursor;
extern CanRxMessage CAN_RxMessage[CAN_RX_MESSAGE_BUFF_SIZE];
extern CanTxMessage CAN_TxMessages[CAN_TX_MESSAGE_BUFF_SIZE];
void init_can(void);
void can_txdat(uint8_t *dat);
#ifdef __cplusplus
}
#endif
#endif
can中断程序
void USB_LP_CAN1_RX0_IRQHandler(void)
{
CAN_ReceiveMessage(CAN1, CAN_FIFO0, &CAN_RxMessage[CAN_RxMessage_Write_Cursor]);
if(CAN_RxMessage_Write_Cursor++>=CAN_RX_MESSAGE_BUFF_SIZE)CAN_RxMessage_Write_Cursor=0;
}
3.2、主程序
线程1发送CAN数据
线程2接收CAN数据
void task1_task(void *pvParameters)
{
uint8_t can_txbuf[8];
uint8_t i=0;
uint8_t cnt=0;
init_can();
for(i=0;i<8;i++)
{
can_txbuf[i]=0;
}
while(1)
{
can_txbuf[0]=cnt;
printf("task1 can txdat[0] !\r\n",can_txbuf[0]);
can_txdat(can_txbuf);
cnt++;
vTaskDelay(1000);
}
}
void task2_task(void *pvParameters)
{
while(1)
{
CAN_Recieve_Process();
vTaskDelay(20);
}
}
四、运行
电路板连接
CAN收发的数据