基于TI-RTOS的CC2650DK开发(26)--- LCD官方示例

来源:互联网 发布:剑三明星捏脸数据 编辑:程序博客网 时间:2024/06/09 21:43

CC2650DK自带的液晶显示屏,官方给出两个示例。之前做的示例由于不了解task,我把代码最简化,现在可以深入一些去学习了。所以先学前面的示例,再来学这个,会简单些。

两个示例,两种不同的使用方法,下面一一道来。示例可从菜单【View】→【Resource Exploer Classic】里得到。


Demo1:lcdSmartRF06EB_CC2650DK_7ID_TI_CC2650F128

先上源码:

/* XDCtools Header files */#include <xdc/std.h>#include <xdc/runtime/System.h>/* BIOS Header files */#include <ti/sysbios/BIOS.h>#include <ti/sysbios/knl/Clock.h>#include <ti/sysbios/knl/Task.h>#include <ti/sysbios/knl/Semaphore.h>/* TI-RTOS Header files */#include <ti/mw/lcd/LCDDogm1286.h>#include <ti/drivers/Power.h>#include <ti/drivers/power/PowerCC26XX.h>#include <ti/drivers/SPI.h>/* Example/Board Header files */#include "Board.h"#define TASKSTACKSIZE   768LCD_Handle lcdHandle = NULL;PIN_Handle pinHandle = NULL;/* LCD使用两个缓冲 */Char lcdBuffer0[LCD_BYTES] = { 0 };Char lcdBuffer1[LCD_BYTES] = { 0 };Task_Struct task0Struct, task1Struct;Char task0Stack[TASKSTACKSIZE], task1Stack[TASKSTACKSIZE];Task_Handle lcdLowPriorityTask, lcdHighPriorityTask;Semaphore_Struct sem0Struct;Semaphore_Handle lcdHighPrioritySem;/* * 把两个LCD缓冲加入数组 */LCD_Buffer lcdBuffers[] ={    { lcdBuffer0, LCD_BYTES, {NULL} },    { lcdBuffer1, LCD_BYTES, {NULL} },};/* * 引脚配置表: *   - 打开LCD的3.3V电源. *   - 关闭LED,其实只用到LED1和LED2. *   - 设置Down按钮中断. */PIN_Config pinTable[] ={    Board_LED1     | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW  | PIN_PUSHPULL | PIN_DRVSTR_MAX,    Board_LED2     | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW  | PIN_PUSHPULL | PIN_DRVSTR_MAX,    Board_LED3     | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW  | PIN_PUSHPULL | PIN_DRVSTR_MAX,    Board_LED4     | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW  | PIN_PUSHPULL | PIN_DRVSTR_MAX,    Board_KEY_DOWN | PIN_INPUT_EN       | PIN_PULLUP    | PIN_IRQ_NEGEDGE,    Board_3V3_EN   | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,    PIN_TERMINATE};/* * ======== gpioButtonFxn ======== *  Down按钮回调函数,用于唤醒高优先级线程 */void gpioButtonFxn(PIN_Handle handle, PIN_Id pinId){    /* 发信号量用于唤醒高优先级线程 */    Semaphore_post(lcdHighPrioritySem);}/* * ======== lcdHighPriorityFxn ======== *  高优先级线程,按下按钮时运行,使用第一个LCD缓冲 */Void lcdHighPriorityFxn(UArg a0, UArg a1){    while (1)    {        //等待信号量        Semaphore_pend(lcdHighPrioritySem, BIOS_WAIT_FOREVER);        //LED2取反        PIN_setOutputValue(pinHandle, Board_LED2, !PIN_getOutputValue(Board_LED2));        /* 在LCD写相应内容 */        LCD_bufferClear(lcdHandle, 0);        LCD_bufferPrintString(lcdHandle, 0, "This is a LCD example", 0, LCD_PAGE0);        LCD_bufferPrintString(lcdHandle, 0, "High Priority Task", 0, LCD_PAGE1);        LCD_bufferPrintString(lcdHandle, 0, "Writing to Buffer 0", 0, LCD_PAGE2);        LCD_bufferPrintStringAligned(lcdHandle, 0, "***", LCD_ALIGN_CENTER, LCD_PAGE4);        LCD_bufferPrintStringAligned(lcdHandle, 0, "*", LCD_ALIGN_CENTER, LCD_PAGE5);        LCD_bufferPrintStringAligned(lcdHandle, 0, "***", LCD_ALIGN_CENTER, LCD_PAGE6);        LCD_update(lcdHandle, 0);    }}/* *  ======== lcdLowPriorityFxn ======== *  低优先级线程 */Void lcdLowPriorityFxn(UArg a0, UArg a1){    LCD_Params lcdParams;    PIN_State  pinState;    uint32_t   counter = 0;    /* 打开引脚 */    pinHandle = PIN_open(&pinState, pinTable);    /* 注册引脚中断函数 */    PIN_registerIntCb(pinHandle, &gpioButtonFxn);    /* 打开LCD驱动实例 */    if (!lcdHandle)    {        LCD_Params_init(&lcdParams);        lcdParams.spiBitRate = 1000000;        lcdHandle = LCD_open(lcdBuffers, 2, &lcdParams);        if (!lcdHandle)        {            System_abort("Error initializing LCD\n");        }    }    /* 写欢迎信息,由于高优先线程一启动就等信号量了,所以此处一定是     * 最先被执行的。也就是评估板启动时的欢迎界面 */    LCD_bufferClear(lcdHandle, 1);    LCD_bufferPrintString(lcdHandle, 1, "Hello SmartRF06EB!", 0, LCD_PAGE0);    LCD_bufferPrintString(lcdHandle, 1, "Low Priority Task", 0, LCD_PAGE1);    LCD_bufferPrintString(lcdHandle, 1, "Writing to Buffer 1", 0, LCD_PAGE2);    LCD_update(lcdHandle, 1);    while (1)    {        /* 每5秒LED1取反一次 */        PIN_setOutputValue(pinHandle, Board_LED1, !PIN_getOutputValue(Board_LED1));        counter++;        if (!(counter % 4))        {            /* 每4次打印计数器的10进制数 */            LCD_bufferPrintString(lcdHandle, 1, "Count value is:", 0, LCD_PAGE4);            LCD_bufferClearPage(lcdHandle, 1, LCD_PAGE5);            LCD_bufferPrintInt(lcdHandle, 1, counter, 1, LCD_PAGE5);            LCD_bufferClearPage(lcdHandle, 1, LCD_PAGE6);            LCD_update(lcdHandle, 1);        }        else        {            /* 其余打印计数器的10、2、16进制数 */            LCD_writeLine(lcdHandle, 1, "Dec", counter, 10, LCD_PAGE4);            LCD_writeLine(lcdHandle, 1, "Bin", counter, 2, LCD_PAGE5);            LCD_writeLine(lcdHandle, 1, "Hex", counter, 16, LCD_PAGE6);        }        /* 线程休眠5秒 */        Task_sleep(5000000 / Clock_tickPeriod);    }}/* *  ======== main ======== * */int main(void){    Task_Params taskParams;    Semaphore_Params semParams;    /* Call board init functions */    Board_initGeneral();    SPI_init();    /* 构造高低优先级task和信号量 */    Task_Params_init(&taskParams);    taskParams.stackSize = TASKSTACKSIZE;    taskParams.stack = &task0Stack;    taskParams.priority = 2;    taskParams.instance->name = "lcdHighPriorityFxn";    Task_construct(&task0Struct, (Task_FuncPtr)lcdHighPriorityFxn, &taskParams, NULL);    lcdHighPriorityTask = Task_handle(&task0Struct);    taskParams.stack = &task1Stack;    taskParams.priority = 1;    taskParams.instance->name = "lcdLowPriorityFxn";    Task_construct(&task1Struct, (Task_FuncPtr)lcdLowPriorityFxn, &taskParams, NULL);    lcdLowPriorityTask = Task_handle(&task1Struct);    Semaphore_Params_init(&semParams);    semParams.mode = Semaphore_Mode_BINARY;    Semaphore_construct(&sem0Struct, 0, &semParams);    lcdHighPrioritySem = Semaphore_handle(&sem0Struct);    /* Start BIOS */    BIOS_start();    return (0);}

此应用程序开了两个task,一个按钮中断,还有一个信号量。两个task的任务是在LCD显示不同内容。

低优先级task:每隔5秒更新一次计数器,并显示于LCD,更新完后就去睡觉了。


高优先级task:等待按钮按下,只要按下按钮,由于优先级高,可以立即抢占低优先级task(当然,大部分时间低优先级task在睡觉,不会抢占),在LCD显示相应内容,然后就继续等等下一次按钮按下了。等待使用的是信号量机制。


按钮中断:按钮按下是硬件中断,当然不能在回调函数里完成复杂功能,如此次的在LCD显示文字,这些东西应该交由task完成。那么,信号量就是完成此项工作的不二人选。按钮按下→触发中断→执行中断回调函数→发出信号量→高优先级task立即接收到信号量→在LCD显示相应内容。

这就是这个程序的基本思路,给人感觉这LCD的使用,太困难了,用得可真难受。法这也正常,此驱动也就这块开发板用了,实际开发根本不可能存在LCD,对于TI来说随便包装包装有得用就不错了。


Demo2:display_CC2650DK_7ID_TI

这是官方有关LCD的第二个Demo,它使用了另一种显示方式,这种方式已经被包装了一层,好用很多。

/* XDCtools Header files */#include <xdc/std.h>#include <xdc/runtime/System.h>/* BIOS Header files */#include <ti/sysbios/BIOS.h>#include <ti/sysbios/knl/Clock.h>#include <ti/sysbios/knl/Task.h>/* TI-RTOS Header files */#include <ti/drivers/PIN.h>#include <ti/mw/display/Display.h>#include <ti/mw/display/DisplayExt.h>/* Board Header files */#include "Board.h"/* Example GrLib image */#include "splash_image.h"#define TASKSTACKSIZE   768Task_Struct task0Struct;Char task0Stack[TASKSTACKSIZE];/* 引脚驱动句柄 */static PIN_Handle ledPinHandle;static PIN_State ledPinState;/* * LED引脚配置表 */PIN_Config ledPinTable[] ={    Board_LED0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,    PIN_TERMINATE};/* *  ======== taskFxn ======== *  task函数 */Void taskFxn(UArg arg0, UArg arg1){    unsigned int ledPinValue;    /* 初始化显示,尝试打开UART和LCD类型显示. */    Display_Params params;    Display_Params_init(¶ms);    params.lineClearMode = DISPLAY_CLEAR_BOTH;    /* 是否成功打开LCD显示和UART显示,取决于主板文件中的Display_config[]数组里     * 是什么内容。     *     * 注意,对于使用SHARP96x96 Watch DevPack的SensorTag评估板来说,有一个引     * 脚和UART冲突,必须排除它,并且UART是首选的。要在Watch DevPack显示,需     * 添加预编译定义BOARD_DISPLAY_EXCLUDE_UART。     */    Display_Handle hDisplayLcd = Display_open(Display_Type_LCD, ¶ms);    Display_Handle hDisplaySerial = Display_open(Display_Type_UART, ¶ms);    //检查是否所选显示状态已经被找到并成功打开    if (hDisplaySerial)    {        Display_print0(hDisplaySerial, 0, 0, "Hello Serial!");    }    if (hDisplayLcd)    {        Display_print0(hDisplayLcd, 5, 3, "Hello LCD!");        /* 等待1秒钟,即可看到LCD显示内容 */        Task_sleep(1000 * (1000 / Clock_tickPeriod));        //如果支持此类显示,使用GrLib扩展来获取LCD的GraphicsLib上下文对象        tContext *pContext = DisplayExt_getGrlibContext(hDisplayLcd);        //有可能无兼容显示可用        if (pContext)        {            /* 画一个图片,我这块开发板未显示此图像 */            GrImageDraw(pContext, &splashImage, 0, 0);            GrFlush(pContext);        }        else        {            /* 只显示了这几行字 */            Display_print0(hDisplayLcd, 0, 0, "Display driver");            Display_print0(hDisplayLcd, 1, 0, "is not");            Display_print0(hDisplayLcd, 2, 0, "GrLib capable!");        }        /* 以上文字显示5秒,然后清除 */        Task_sleep(5000 * (1000 / Clock_tickPeriod));        Display_clear(hDisplayLcd);    }    /* 无限循环,LED闪烁并在LCD显示 */    while (1)    {        ledPinValue = PIN_getOutputValue(Board_LED0);        if (hDisplayLcd)        {            /* 清除LCD的第一行并显示相应文字 */            Display_clearLine(hDisplayLcd, ledPinValue ? 0 : 1);            Display_print1(hDisplayLcd, ledPinValue ? 1 : 0, 0, "LED: %s",                           (!ledPinValue) ? "On!" : "Off!");        }        if (hDisplaySerial)        {            /* 打印到UART口 */            Display_print1(hDisplaySerial, 0, 0, "LED: %s",                           (!ledPinValue) ? "On!" : "Off!");        }        /* 切换LED */        PIN_setOutputValue(ledPinHandle, Board_LED0,                           !PIN_getOutputValue(Board_LED0));        Task_sleep((UInt)arg0);//挂起1秒    }}/* *  ======== main ======== */int main(void){    Task_Params taskParams;    /* Call board init functions */    Board_initGeneral();    /* Construct heartBeat Task  thread */    Task_Params_init(&taskParams);    taskParams.arg0 = 1000000 / Clock_tickPeriod;    taskParams.stackSize = TASKSTACKSIZE;    taskParams.stack = &task0Stack;    Task_construct(&task0Struct, (Task_FuncPtr)taskFxn, &taskParams, NULL);    /* Open LED pins */    ledPinHandle = PIN_open(&ledPinState, ledPinTable);    if(!ledPinHandle)    {        System_abort("Error initializing board LED pins\n");    }    PIN_setOutputValue(ledPinHandle, Board_LED0, 1);    System_printf("Starting the example\nSystem provider is set to SysMin. "                  "Halt the target to view any SysMin contents in ROV.\n");    /* SysMin will only print to the console when you call flush or exit */    System_flush();    /* Start BIOS */    BIOS_start();    return (0);}
这个例子架构很简单,开一个task,每隔1秒交替亮灭LED灯,并在LCD上显示LED:ON和LED:OFF。

开发板启动时应该显示一幅图像,我这块板没显示,应该是不支持GrLib。

官方的例子看完了,为了显示自己已经理解这些代码,就必须写一个例子,那就写个更简单的例子吧。




0 0
原创粉丝点击