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

原创 2017年01月03日 23:52:47

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   768

LCD_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   768

Task_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。

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




版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

CC2640之配置串口打印及可变参数打印

TI的CC2640协议栈中的Demo大多数默认是没有打开串口的,这主要是因为低功耗功能的需要,但是我们平常的开发调试过程中,非常需要打印一些变量等信息来便于问题的查找和分析...

TI CC2650 学习历程(一)

最近在调研TI的CC2650,现将整理的资料做个笔记,也当作个备份,方便查阅,以希望能帮到大家。 官方资料 论坛资料 1 官方资料 官网:http://www.ti.com/ww...

UCOSII 信号量和信号量集实例

代码来自于书本光盘 《嵌入式操作系统UCOSII原理及应用》 实例1信号量 #include "includes.h" #define  TASK_STK_SIZE   512 //...

CCS+DSP 环境搭建

之前的demo是TI烧写好的,现在要自己编译调试程序,首先要搭建环境,根据赠送光盘中说明: 第一步:安装CCS,这里我没有安装光盘赠送的CCSv5.2,而是到官网下载的CCSv5.5,默认安装到C盘T...

基于TI-RTOS的CC2650DK开发(30)--- Swi官方示例

官方示例中有一个专门针对Swi的例子,它演示了Swi的几种提交方法,基本针对Swi的几种提交方法写的程序,在读此程序之前请先阅读这篇日志。 先上代码: /* XDC module Headers ...
  • abatei
  • abatei
  • 2017年01月10日 09:16
  • 600

基于TI-RTOS的CC2650DK开发(9)---任务示例

共两个例子,实在太长,所以开新日志来写。先来书上的第一个例子,这回按照书上的做又有问题,好在花了点时间还是找到问题所在。以下代码至少在CC2650DK上是可以运行的。 3.6.5.6 Tas...
  • abatei
  • abatei
  • 2016年12月16日 09:25
  • 966

基于TI-RTOS的CC2650DK开发(27)--- 邮箱示例

本想用semaphore搞个简单的LCD示例,也就是按一个按钮,将按钮值显示在LCD上。但写的时候突然发现semaphore无法实现这个功能啊。因为要在一个task内显示按钮值,而按钮有5个,显示5个...
  • abatei
  • abatei
  • 2017年01月06日 23:42
  • 709

基于TI-RTOS的CC2650DK开发(5)---线程概览

再学下去就必须理解RTOS中的线程了,这是必须要跨过的坎,好在TI有详细的资料:《 SYS/BIOS(TI-RTOS Kernel) v4.64 User's Guide》这本PDF手册里对线程有详细...
  • abatei
  • abatei
  • 2016年12月12日 08:14
  • 1415

基于TI-RTOS的CC2650DK开发(25)---IOM接口

本附录提供IOM(I/O迷你驱动)接口的详细描述。 F.1  迷你驱动接口概览 迷你驱动接口指定了如何实现一个迷你驱动。 功能 一个迷你驱动应当实现以下...
  • abatei
  • abatei
  • 2017年01月01日 10:17
  • 430

基于TI-RTOS的CC2650DK开发(12)---事件模块

4.2 事件模块 事件为线程间的通信和同步提供了一种手段。它和Semaphores类似,除了它们允许你在等待线程返回之前可以指定必须发生的多个条件(“事件”)。 事件实例和Se...
  • abatei
  • abatei
  • 2016年12月19日 09:31
  • 895
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:基于TI-RTOS的CC2650DK开发(26)--- LCD官方示例
举报原因:
原因补充:

(最多只允许输入30个字)