FreeRTOS LCD Demo1

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wowocpp/article/details/82701234

该例子来自:
FreeRTOSV8.2.3\FreeRTOS\Demo\CORTEX_LM3S811_KEIL\
FreeRTOSV8.2.3\FreeRTOS\Demo\CORTEX_STM32F103_Keil

1 例子解析

This project contains an application demonstrating the use of the
FreeRTOS.org mini real time scheduler on the Luminary Micro LM3S811 Eval
board. See http://www.FreeRTOS.org for more information.

main() simply sets up the hardware, creates all the demo application tasks,
then starts the scheduler. http://www.freertos.org/a00102.html provides
more information on the standard demo tasks.

In addition to a subset of the standard demo application tasks, main.c also
defines the following tasks:

  • A ‘Print’ task. The print task is the only task permitted to access the
    LCD - thus ensuring mutual exclusion and consistent access to the resource.
    Other tasks do not access the LCD directly, but instead send the text they
    wish to display to the print task. The print task spends most of its time
    blocked - only waking when a message is queued for display.
    Print 任务 唯一的一个,允许访问LCD的任务。
    确保互斥和一致的 访问资源
    其他的任务不能够直接的访问 LCD。
    但是可以发送要显示的text到print task。
    print task大多数时间正在阻塞,等待消息发送过来。

  • A ‘Button handler’ task. The eval board contains a user push button that
    is configured to generate interrupts. The interrupt handler uses a
    semaphore to wake the button handler task - demonstrating how the priority
    mechanism can be used to defer interrupt processing to the task level. The
    button handler task sends a message both to the LCD (via the print task) and
    the UART where it can be viewed using a dumb terminal (via the UART to USB
    converter on the eval board). NOTES: The dumb terminal must be closed in
    order to reflash the microcontroller. A very basic interrupt driven UART
    driver is used that does not use the FIFO. 19200 baud is used.

Button handler 任务,板子包括一个按钮,配置来产生中断。中断 使用semaphore(信号量)
来唤醒 button handler task,
用来演示使用的优先级机制,来推迟中断处理到任务级别。
button handler task 发送消息给 LCD 和 UART两个任务。

  • A ‘check’ task. The check task only executes every five seconds but has a
    high priority so is guaranteed to get processor time. Its function is to
    check that all the other tasks are still operational and that no errors have
    been detected at any time. If no errors have every been detected ‘PASS’ is
    written to the display (via the print task) - if an error has ever been
    detected the message is changed to ‘FAIL’. The position of the message is
    changed for each write.

check 任务 ,只是5s执行一次,但是有最高的优先级。
他的任务是检查所有的其他的任务是否仍然在运行。而且是否检测到error。
如果没有errors 在LCD 上面显示PASS。如果有错误 显示 FAIL。
消息的位置每次都不一样。

2 在 Nu_LB_140 上面运行 MCU_init.h

MCU_init.h

//Define Clock source
#define MCU_CLOCK_SOURCE      
#define MCU_CLOCK_SOURCE_HIRC // HXT, LXT, HIRC, LIRC
#define MCU_CLOCK_FREQUENCY   50000000  //Hz


//Define MCU Interfaces
#define MCU_INTERFACE_UART0
#define UART_CLOCK_SOURCE_HIRC // HXT, LXT, PLL, HIRC
#define UART_CLOCK_DIVIDER     3
#define PIN_UART0_RX_PB0
#define PIN_UART0_TX_PB1


#define MCU_INTERFACE_INT1_PB15


//Define MCU Interfaces
#define MCU_INTERFACE_SPI3
#define SPI3_CLOCK_SOURCE_HCLK // HCLK, PLL
#define PIN_SPI3_SS0_PD8
#define PIN_SPI3_SCLK_PD9
#define PIN_SPI3_MISO0_PD10
#define PIN_SPI3_MOSI0_PD11



//Define MCU Interfaces
#define MCU_INTERFACE_UART1
#define UART_CLOCK_SOURCE_HIRC // HXT, LXT, PLL, HIRC
#define UART_CLOCK_DIVIDER     3
#define PIN_UART1_RX_PB4
#define PIN_UART1_TX_PB5



//Define MCU Interfaces

3 在 Nu_LB_140 上面运行 main.c

main.c

//
// 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"
#include "LCD.h"


/* Demo task priorities. */
#define mainQUEUE_POLL_PRIORITY     ( tskIDLE_PRIORITY + 2 )
#define mainCHECK_TASK_PRIORITY     ( tskIDLE_PRIORITY + 3 )
#define mainSEM_TEST_PRIORITY       ( tskIDLE_PRIORITY + 1 )
#define mainBLOCK_Q_PRIORITY        ( tskIDLE_PRIORITY + 2 )

/* Misc. */
#define mainQUEUE_SIZE              ( 12 )
#define mainDEBOUNCE_DELAY          ( ( TickType_t ) 150 / portTICK_PERIOD_MS )
#define mainNO_DELAY                ( ( TickType_t ) 0 )

#define THREAD_TEST_STACK_SIZE  configMINIMAL_STACK_SIZE    
#define THREAD_TEST_PRIORITY    ( tskIDLE_PRIORITY + 1 )

/* The queue used to hold received characters. */
static QueueHandle_t xRxedChars;
static QueueHandle_t xCharsForTx;


void Thread_Task1( void *pvParameters );
void Thread_Task2( void *pvParameters );


/*
 * The task that is woken by the ISR that processes GPIO interrupts originating
 * from the push button.
 */
static void vButtonHandlerTask( void *pvParameters );

/*
 * The task that controls access to the LCD.
 */
static void vPrintTask( void *pvParameter );


/* The semaphore used to wake the button handler task from within the GPIO
interrupt handler. */
SemaphoreHandle_t xButtonSemaphore;

/* The queue used to send strings to the print task for display on the LCD. */
QueueHandle_t xPrintQueue;


typedef struct
{
    long xColumn;
    signed char *pcMessage;
} xLCDMessage;

static void vComTxTask( void *pvParameters );

static void vComRxTask( void *pvParameters );

void vStartThreadTasks( void )
{

    /* Create the semaphore used to wake the button handler task from the GPIO
    ISR. */

    vSemaphoreCreateBinary( xButtonSemaphore );

    xSemaphoreTake( xButtonSemaphore, 0 );

    xRxedChars = xQueueCreate( 26, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
    xCharsForTx = xQueueCreate( 26, ( unsigned portBASE_TYPE ) sizeof( signed char ) );


    /* Create the queue used to pass message to vPrintTask. */
    xPrintQueue = xQueueCreate( 3, sizeof( xLCDMessage ) );

    xTaskCreate( Thread_Task1, (const  char * ) "Th_Task1", THREAD_TEST_STACK_SIZE, NULL, THREAD_TEST_PRIORITY, ( xTaskHandle * ) NULL );

//  xTaskCreate( Thread_Task2, (const  char * ) "Th_Task2", THREAD_TEST_STACK_SIZE, NULL, THREAD_TEST_PRIORITY, ( xTaskHandle * ) NULL );

    xTaskCreate( vButtonHandlerTask, "Status", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY + 1, NULL );

    xTaskCreate( vPrintTask, "Print", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY - 1, NULL );

    /* The Tx task is spawned with a lower priority than the Rx task. */
    xTaskCreate( vComRxTask, "COMRx", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, ( TaskHandle_t * ) NULL );

}



static void vPrintTask( void *pvParameters )
{

    xLCDMessage xMessage;
    unsigned portBASE_TYPE uxLine = 0, uxRow = 0;

    for( ;; )
    {
        /* Wait for a message to arrive. */
        xQueueReceive( xPrintQueue, &xMessage, portMAX_DELAY );
        printf("LCD %s End\r\n",xMessage.pcMessage);
        /* Write the message to the LCD. */
        uxRow++;
        uxLine++;

        if(xMessage.xColumn ==0){

            print_Line(0,"            ");
            print_Line(0, ( char * ) xMessage.pcMessage);
        }

        if(xMessage.xColumn ==1){

            print_Line(1,"            ");
            print_Line(1, ( char * ) xMessage.pcMessage);
        }       

    }
}



static void vButtonHandlerTask( void *pvParameters )
{


    static signed char cPassMessage[10];

    static unsigned short cnt = 0;

    int  i = 0 ;

    xLCDMessage xMessage;

    xMessage.pcMessage = cPassMessage;

    xMessage.xColumn = 0 ;


    for( ;; )
    {
        /* Wait for a GPIO interrupt to wake this task. */
        while( xSemaphoreTake( xButtonSemaphore, portMAX_DELAY ) != pdPASS );
        printf("button\r\n");

        for(i=0;i<10;i++){

            cPassMessage[i] = 0 ;
        }
        sprintf( ( char * ) cPassMessage, "PASS %d", cnt);
        cnt = cnt +1 ;

        if(cnt ==20){
             cnt = 0 ;
        }

        //printf("%s\r\n",xMessage.pcMessage);
        /* Queue a message for the print task to display on the LCD. */
        xQueueSend( xPrintQueue, &xMessage, portMAX_DELAY );

        /* Make sure we don't process bounces. */
        vTaskDelay( mainDEBOUNCE_DELAY );
        xSemaphoreTake( xButtonSemaphore, mainNO_DELAY );
    }
}



void Thread_Task1( void *pvParameters )
{
    portTickType xLastTime1;

    /* Get current system TickCount. */
    xLastTime1 = xTaskGetTickCount();

    for( ;; )
    {
        /* Run a time every 400 milliseconds. */
        vTaskDelayUntil( &xLastTime1, 1500 );

        //printf("Task1 called-\n");
              GPIO_TOGGLE(PC12);
    }   
}

void Thread_Task2( void *pvParameters )
{
    portTickType xLastTime2;

    /* Get current system TickCount. */
    xLastTime2 = xTaskGetTickCount();   

    for( ;; )
    {
        /* Run a time every 800 milliseconds. */
        vTaskDelayUntil( &xLastTime2, 800 );
        printf("Task2 called--\n");
    }
}


void EINT1_IRQHandler(void)
{   
    portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

    /* Clear the interrupt. */
  GPIO_CLR_INT_FLAG(PB, BIT15); // Clear GPIO interrupt flag
  printf("PB15 EINT1 occurred.\n");
    PC12 = 0;
    /* Wake the button handler task. */
    xSemaphoreGiveFromISR( xButtonSemaphore, &xHigherPriorityTaskWoken );
  portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );            
}

void Init_EXTINT(void)
{

    // Configure EINT1 pin and enable interrupt by rising and falling edge trigger
    GPIO_SetMode(PB, BIT15, GPIO_MODE_INPUT);
    GPIO_EnableEINT1(PB, 15, GPIO_INT_RISING); // RISING, FALLING, BOTH_EDGE, HIGH, LOW
    NVIC_EnableIRQ(EINT1_IRQn);

    // Enable interrupt de-bounce function and select de-bounce sampling cycle time
    GPIO_SET_DEBOUNCE_TIME(GPIO_DBCLKSRC_LIRC, GPIO_DBCLKSEL_64);
    GPIO_ENABLE_DEBOUNCE(PB, BIT15);
}


void UART1_IRQHandler(void)
{

    portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

    char cChar; 


    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 );

}


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;
    }
}


static void vComRxTask( void *pvParameters )
{
    signed char  cByteRxed;

    xLCDMessage xMessage;

    static signed char cPassMessage[10];    

    int i = 0 ;

    xMessage.pcMessage = cPassMessage;

    xMessage.xColumn = 1;

    for( ;; )
    {

            /* Block on the queue that contains received bytes until a byte is
            available. */
            if( xSerialGetChar(&cByteRxed, ( ( TickType_t ) 0xffff ) ) )
            {


                for(i=0;i<10;i++){

                    cPassMessage[i] = 0 ;
                }

                cPassMessage[0] = cByteRxed ;

                xQueueSend( xPrintQueue, &xMessage, portMAX_DELAY );

            }       
    }

} 



int main(void)
{
    SYS_Init();      
        UART_Open(UART0, 115200);
        printf("Hello World \r\n"); 

        UART_Open(UART1,115200);  // enable UART1 at 115200 baudrate
    UART_ENABLE_INT(UART1, UART_IER_RDA_IE_Msk);
    NVIC_EnableIRQ(UART1_IRQn);


    init_LCD();
    clear_LCD();

    print_Line(2, "128KB Flash ROM ");
    print_Line(3, "32KB  SRAM      ");      


    GPIO_SetMode(PC, BIT12, GPIO_MODE_OUTPUT);

      vStartThreadTasks();


        Init_EXTINT();  

    vTaskStartScheduler();


    while(1) ;
}

4 功能描述

LCD的第0行,显示PASS 数字
数字为从0到19,
按下 按键SW_INT1 一下 数字加1 达到20的时候,自动清零

LCD的第1行,显示从UART1接收的最后一个字符。

显示效果如下:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/wowocpp/article/details/82701234
LCD