参考例子:
Nu_LB_NUC140_BSP\ThirdParty\FreeRTOS\Demo\CORTEX_STM32F103_Keil
FreeRTOS_Serial
参考链接:
https://blog.csdn.net/wowocpp/article/details/81982665
1 串口硬件:
2 功能简介
UART1 间隔一定的时间 发送 ABCDEFGHIJKLMNOPQRSTUVWX 字符串,共24个字节
同时 UART1 准备接收 ABCDEFGHIJKLMNOPQRSTUVWX 字符串,如果字符串不对,会报错。
系统的log 信息,是通过 UART0 打印的。
3 代码
//
// GPIO_LED : GPIO output to control an on-board red LED
//
// EVB : Nu-LB-NUC140
// MCU : NUC140VE3CN
// low-active output control by GPC12
#include <stdio.h>
#include "NUC100Series.h"
#include "MCU_init.h"
#include "SYS_init.h"
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"
/* The queue used to hold received characters. */
static QueueHandle_t xRxedChars;
static QueueHandle_t xCharsForTx;
static void vComTxTask( void *pvParameters );
static void vComRxTask( void *pvParameters );
void vParTestToggleLED( unsigned portBASE_TYPE uxLED )
{
unsigned short usBit;
vTaskSuspendAll();
if(uxLED == 0){
GPIO_TOGGLE(PC12);
}
if(uxLED == 1){
GPIO_TOGGLE(PC14);
}
xTaskResumeAll();
}
void vParTestSetLED( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue )
{
unsigned short usBit;
vTaskSuspendAll();
if(uxLED == 0){
if( xValue == pdFALSE ){
PC12 = 1 ; // off
}else{
PC12 = 0 ; // on
}
}
if(uxLED == 1){
if( xValue == pdFALSE ){
PC14 = 1 ;
}else{
PC14 = 0 ;
}
}
xTaskResumeAll();
}
signed portBASE_TYPE xSerialPutChar(signed char cOutChar, TickType_t xBlockTime )
{
signed portBASE_TYPE xReturn;
if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) == pdPASS )
{
xReturn = pdPASS;
UART_ENABLE_INT(UART1,UART_IER_THRE_IEN_Msk);
}
else
{
xReturn = pdFAIL;
}
return xReturn;
}
static void vComTxTask( void *pvParameters )
{
char cByteToSend;
TickType_t xTimeToWait;
for( ;; )
{
for( cByteToSend = 'A'; cByteToSend <= 'X'; cByteToSend++ )
{
if( xSerialPutChar(cByteToSend, 0 ) == pdPASS )
{
vParTestToggleLED( 0 );
}
}
vParTestSetLED( 0, pdFALSE );
xTimeToWait = xTaskGetTickCount() + 3;
/* Make sure we don't wait too long... */
xTimeToWait %= 0x96;
/* ...but we do want to wait. */
if( xTimeToWait < 0x32 )
{
xTimeToWait = 0x32;
}
vTaskDelay( xTimeToWait );
}
}
signed portBASE_TYPE xSerialGetChar(signed char *pcRxedChar, TickType_t xBlockTime )
{
/* Get the next character from the buffer. Return false if no characters
are available, or arrive before xBlockTime expires. */
if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )
{
return pdTRUE;
}
else
{
return pdFALSE;
}
}
/* Check variable used to ensure no error have occurred. The Rx task will
increment this variable after every successfully received sequence. If at any
time the sequence is incorrect the the variable will stop being incremented. */
static volatile UBaseType_t uxRxLoops = 0;
static void vComRxTask( void *pvParameters )
{
signed char cExpectedByte, cByteRxed;
BaseType_t xResyncRequired = pdFALSE, xErrorOccurred = pdFALSE;
for( ;; )
{
/* We expect to receive the characters from comFIRST_BYTE to
comLAST_BYTE in an incrementing order. Loop to receive each byte. */
for( cExpectedByte = 'A'; cExpectedByte <= 'X'; cExpectedByte++ )
{
/* Block on the queue that contains received bytes until a byte is
available. */
if( xSerialGetChar(&cByteRxed, ( ( TickType_t ) 0xffff ) ) )
{
/* Was this the byte we were expecting? If so, toggle the LED,
otherwise we are out on sync and should break out of the loop
until the expected character sequence is about to restart. */
printf("%c",cByteRxed);
if( cByteRxed == cExpectedByte )
{
vParTestToggleLED( 1);
}
else
{
xResyncRequired = pdTRUE;
break; /*lint !e960 Non-switch break allowed. */
}
}
}
/* Turn the LED off while we are not doing anything. */
vParTestSetLED( 1, pdFALSE );
/* Did we break out of the loop because the characters were received in
an unexpected order? If so wait here until the character sequence is
about to restart. */
if( xResyncRequired == pdTRUE )
{
printf(" vComRxTask Error\r\n");
while( cByteRxed != 'X' )
{
/* Block until the next char is available. */
xSerialGetChar(&cByteRxed, ( TickType_t ) 0xffff );
}
printf("Err22--0x%x\r\n",cByteRxed);
/* Note that an error occurred which caused us to have to resync.
We use this to stop incrementing the loop counter so
sAreComTestTasksStillRunning() will return false - indicating an
error. */
xErrorOccurred++;
/* We have now resynced with the Tx task and can continue. */
xResyncRequired = pdFALSE;
}
else
{
if( xErrorOccurred < 6 )
{
/* Increment the count of successful loops. As error
occurring (i.e. an unexpected character being received) will
prevent this counter being incremented for the rest of the
execution. Don't worry about mutual exclusion on this
variable - it doesn't really matter as we just want it
to change. */
uxRxLoops++;
}
}
}
}
void vStartThreadTasks( void )
{
/* Initialise the com port then spawn the Rx and Tx tasks. */
/* Create the queues used to hold Rx/Tx characters. */
xRxedChars = xQueueCreate( 26, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
xCharsForTx = xQueueCreate( 26, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
/* The Tx task is spawned with a lower priority than the Rx task. */
xTaskCreate( vComTxTask, "COMTx", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY , ( TaskHandle_t * ) NULL );
xTaskCreate( vComRxTask, "COMRx", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, ( TaskHandle_t * ) NULL );
}
void UART1_IRQHandler(void)
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
char cChar;
uint8_t in_char;
if(UART_IS_RX_READY(UART1)) {
cChar = UART_READ(UART1);
//printf("%c",cChar);
xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );
}
if(UART_IS_TX_EMPTY(UART1)){
/* The interrupt was caused by the THR becoming empty. Are there any
more characters to transmit? */
if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE )
{
/* A character was retrieved from the queue so can be sent to the
THR now. */
UART_WRITE(UART1, cChar);
}
else
{
UART_DISABLE_INT(UART1,UART_IER_THRE_IEN_Msk);
}
}
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
int main(void)
{
SYS_Init();
UART_Open(UART0, 115200);
printf("Hello World \r\n");
GPIO_SetMode(PC, BIT12, GPIO_MODE_OUTPUT);
GPIO_SetMode(PC, BIT14, GPIO_MODE_OUTPUT);
UART_Open(UART1,115200); // enable UART1 at 115200 baudrate
UART_ENABLE_INT(UART1, UART_IER_RDA_IE_Msk);
NVIC_EnableIRQ(UART1_IRQn);
vStartThreadTasks();
vTaskStartScheduler();
while(1);
}
5 主要研究的地方
队列
队列大小
队列接收和发送操作是原子操作吗
E:\Nu_LB_Nuc140\Nu_LB_NUC140_BSP\SampleCode\Nu-LB-NUC140\FreeRTOS_Serial
(稍后补充)