FreeRTOS系统下实现LED灯闪烁

上一章用IDE创建了包含2个应用的FreeRTOS工程,工程代码中关于应用的部分代码是空的,待开发者自己实现。
本章就通过实现一个LED灯闪烁来介绍一下FreeRTOS下的应用编程。

1.系统初始化介绍

int main ( void )
{
    /* Initialize all modules */
    SYS_Initialize ( NULL );

    while ( true )
    {
        /* Maintain state machines of all polled MPLAB Harmony modules. */
        SYS_Tasks ( );
    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}

这里是IDE生成的main函数部分,首先是SYS_Initialize函数,主要是中断、时钟、cache、ram、各类外设的初始化。

void SYS_Initialize ( void* data )
{

    /* MISRAC 2012 deviation block start */
    /* MISRA C-2012 Rule 2.2 deviated in this file.  Deviation record ID -  H3_MISRAC_2012_R_2_2_DR_1 */

    /* Start out with interrupts disabled before configuring any modules */
    (void)__builtin_disable_interrupts();

  
    CLK_Initialize();

    /* Configure KSEG0 as cacheable memory. This is needed for Prefetch Buffer */
    __builtin_mtc0(16, 0,(__builtin_mfc0(16, 0) | 0x3U));

    /* Configure Flash Wait States and Prefetch */
    CHECONbits.PFMWS = 1;
    CHECONbits.PREFEN = 3;

    /* Set the SRAM wait states to One */
    BMXCONbits.BMXWSDRM = 1;

    /* Configure Debug Data Port */
    DDPCONbits.JTAGEN = 0;



	GPIO_Initialize();

    CORETIMER_Initialize();

    /* MISRAC 2012 deviation block start */
    /* Following MISRA-C rules deviated in this block  */
    /* MISRA C-2012 Rule 11.3 - Deviation record ID - H3_MISRAC_2012_R_11_3_DR_1 */
    /* MISRA C-2012 Rule 11.8 - Deviation record ID - H3_MISRAC_2012_R_11_8_DR_1 */

    /* MISRA C-2012 Rule 11.3, 11.8 deviated below. Deviation record ID -  
    H3_MISRAC_2012_R_11_3_DR_1 & H3_MISRAC_2012_R_11_8_DR_1*/
        
    sysObj.sysTime = SYS_TIME_Initialize(SYS_TIME_INDEX_0, (SYS_MODULE_INIT *)&sysTimeInitData);
    
    /* MISRAC 2012 deviation block end */

    /* MISRAC 2012 deviation block end */
	LED_Initialize();
    EEPROM_Initialize();
    
    EVIC_Initialize();
    
    /* Enable global interrupts */
    (void)__builtin_enable_interrupts();

    /* MISRAC 2012 deviation block end */
}

2.GPIO模式配置

要实现一个LED灯的闪烁,我们需要初始化控制led电路的开关的GPIO为输出模式,然后再定时改变GPIO输出的高低电平即可实现LED的闪烁。在GPIO_Initialize函数中进行IO的模式设定。
实现IO的模式可通过2种方式,直接操作寄存器实现或者通过API实现。
以A0为例子,通过寄存器实现:

_TRISA0 = 0; //A0为输出模式
_RA0 = 0; //A0输出低电平

亦可直接调用API实现,打开plib_gpio.h文件,发现

static inline void GPIO_PinOutputEnable(GPIO_PIN pin)
{
    GPIO_PortOutputEnable((GPIO_PORT)(pin>>4U), 0x1UL << (pin & 0xFU));
}

void GPIO_PortOutputEnable(GPIO_PORT port, uint32_t mask)
{
    *(volatile uint32_t *)(&TRISACLR + (port * 0x10U)) = mask;
}

此API是通过先对PIC32MX795的112个GPIO进行编号,通过序号来找到对应IO寄存器地址实现模式的设置。A0是第一个IO,初始化代码如下:

GPIO_PinOutputEnable(GPIO_PIN_RA0);//头文件中已经对112个IO进行了宏定义
GPIO_PinClear(GPIO_PIN_RA0); // A0设为低电平

3. Led 任务初始化

typedef struct
{
    /* The application's current state */
    LED_STATES state;

    /* TODO: Define any additional data used by the application. */

} LED_DATA;

void LED_Initialize ( void )
{
    /* Place the App state machine in its initial state. */
    ledData.state = LED_STATE_INIT;



    /* TODO: Initialize your application's state machine and other
     * parameters.
     */
}

这里只是初始化了ledData的状态为初始化状态。

3.系统任务函数

void SYS_Tasks ( void )
{
    /* Maintain system services */
    

    /* Maintain Device Drivers */
    

    /* Maintain Middleware & Other Libraries */
    

    /* Maintain the application's state machine. */
        /* Create OS Thread for LED_Tasks. */
    (void) xTaskCreate((TaskFunction_t) lLED_Tasks,
                "LED_Tasks",
                1024,
                NULL,
                1,
                &xLED_Tasks);

    /* Create OS Thread for EEPROM_Tasks. */
    (void) xTaskCreate((TaskFunction_t) lEEPROM_Tasks,
                "EEPROM_Tasks",
                1024,
                NULL,
                1,
                &xEEPROM_Tasks);




    /* Start RTOS Scheduler. */
    
     /**********************************************************************
     * Create all Threads for APP Tasks before starting FreeRTOS Scheduler *
     ***********************************************************************/
    vTaskStartScheduler(); /* This function never returns. */

}

此函数内使用了xTaskCreate函数创建了2个线程,并开启任务调度。

/* Handle for the LED_Tasks. */
TaskHandle_t xLED_Tasks;

static void lLED_Tasks(  void *pvParameters  )
{   
    while(true)
    {
        LED_Tasks();
        vTaskDelay(100U / portTICK_PERIOD_MS);
    }
}

lLED_Tasks内每100ms执行以下LED_Tasks函数。

void LED_Tasks ( void )
{

    /* Check the application's current state. */
    switch ( ledData.state )
    {
        /* Application's initial state. */
        case LED_STATE_INIT:
        {
            bool appInitialized = true;

            if (appInitialized)
            {

                ledData.state = LED_STATE_SERVICE_TASKS;
            }
            break;
        }

        case LED_STATE_SERVICE_TASKS:
        {

            break;
        }

        /* TODO: implement your application state machine.*/


        /* The default state should never be executed. */
        default:
        {
            /* TODO: Handle error in application's state machine. */
            break;
        }
    }
}

4.实现LED闪烁

LED_Tasks分为2种模式,init模式和service模式。可以在init模式进行IO的设置。由于我们之前在GPIO_Initialize函数中已经对IO进行了初始化设置。这里就暂不做处理了。
在service模式下编写功能即可。在之前的LED_DATA结构体内增加一个io状态变量。

typedef struct
{
    /* The application's current state */
    LED_STATES state;
    uint8_t io_status;
    /* TODO: Define any additional data used by the application. */

} LED_DATA;

实现IO状态翻转

void LED_Tasks ( void )
{

    /* Check the application's current state. */
    switch ( ledData.state )
    {
        /* Application's initial state. */
        case LED_STATE_INIT:
        {
            bool appInitialized = true;

            if (appInitialized)
            {

                ledData.state = LED_STATE_SERVICE_TASKS;
            }
            break;
        }

        case LED_STATE_SERVICE_TASKS:
        {
            if(ledData.io_status == 0)
                GPIO_PinClear(GPIO_PIN_RA0);
            else
                GPIO_PinSet(GPIO_PIN_RA0);
            
            ledData.io_status = !ledData.io_status;
            break;
        }

        /* TODO: implement your application state machine.*/


        /* The default state should never be executed. */
        default:
        {
            /* TODO: Handle error in application's state machine. */
            break;
        }
    }
}

此处需要在led.c中添加“ #include “config/default/peripheral/gpio/plib_gpio.h” ”,解决编译错误。
编译完成,程序烧录完成后led即开始闪烁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值