基于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。
官方的例子看完了,为了显示自己已经理解这些代码,就必须写一个例子,那就写个更简单的例子吧。
- 基于TI-RTOS的CC2650DK开发(26)--- LCD官方示例
- 基于TI-RTOS的CC2650DK开发(30)--- Swi官方示例
- 基于TI-RTOS的CC2650DK开发(9)---任务示例
- 基于TI-RTOS的CC2650DK开发(27)--- 邮箱示例
- 基于TI-RTOS的CC2650DK开发(4)---DOGM128W-6 LCD显示
- 基于TI-RTOS的CC2650DK开发(2)---点亮LED
- 基于TI-RTOS的CC2650DK开发(5)---线程概览
- 基于TI-RTOS的CC2650DK开发(6)---硬件中断
- 基于TI-RTOS的CC2650DK开发(7)---软件中断
- 基于TI-RTOS的CC2650DK开发(8)---任务
- 基于TI-RTOS的CC2650DK开发(10)---空闲循环
- 基于TI-RTOS的CC2650DK开发(11)---信号量
- 基于TI-RTOS的CC2650DK开发(12)---事件模块
- 基于TI-RTOS的CC2650DK开发(13)---门
- 基于TI-RTOS的CC2650DK开发(14)---邮箱
- 基于TI-RTOS的CC2650DK开发(17)---支持模块
- 基于TI-RTOS的CC2650DK开发(21)---检测
- 基于TI-RTOS的CC2650DK开发(22)--- 时间基准
- opencv学习三种常用方法访问操作图像像素
- sublime3安装配置找寻到的有用资料
- 浅谈Mac OS下SVN的使用方法(下)
- iptables规则的删除-怎么删除一条已有的iptables规则
- 测试
- 基于TI-RTOS的CC2650DK开发(26)--- LCD官方示例
- 【原创】简单尝试脱“爱加密”官网加固的DEX壳
- 详解游戏中的旋转坐标变换
- 每天一个 Linux 命令(22):find 命令的参数详解
- opnet调试之进程调试
- MyBatis中使用bind标签构造模糊查询失败的解决方法
- 使用 Struts2 校验器校验用户注册信息的例子
- [整理]Windbg常用命令一览
- Python第八天