[LOOK] 学习体会第八贴——LOOK中使用TFT屏【二】有总结有疑惑

[复制链接]
3449|10
 楼主| gdmgb520 发表于 2011-10-2 14:31 | 显示全部楼层 |阅读模式
本帖最后由 gdmgb520 于 2011-10-2 14:35 编辑

实现的功能:
在我前一帖的基础上,使用了Timer。系统中跑两个任务,Timer任务用来计时,设置计时间隔为1000ms,对应显示屏上的Timer Timer:xxxxx;task_led1任务用来刷新屏幕,刷新间隔通过修改REFRESH_TIMES宏来设定,该任务刷新周期是通过延时实现,同时,在该任务中每延时到1s时间,计数器加1,对应屏上Running Time:xxxxx。

对程序的说明:
1.程序中有些代码没有用到的,为方便大家阅读已经删除。
2.Timer的程序是根据菜农大叔 LOOK_TIMER.rar 例程添加的,应该如果看懂了这个例程,那Timer就会用了。我还没完全看懂。
3.LOOK_TIMER 例程的脉络:
主线一,Timer任务:
step1.定时器定时时间到
step2.on_signal()函数内的if语句被执行,流水灯显示。
主线二,按键中断:
step1.当按键中断产生时,按键中断调用task_LOOK_TIMER_t类的成员函数send_message(-50),把一个参数-50发送到邮箱。
step2.task_LOOK_TIMER对象的routine()函数通过mbox.get()获取到该参数,并使用该参数修改定时器的interval值。

学习时遇到的疑惑以及在学习中的自问自答(希望能跟大家讨论):
1.timer类的构造函数
  1. // 任务类 LOOK_TIMER 的构造函数
  2. __INLINE__ task_LOOK_TIMER_t::task_LOOK_TIMER_t()
  3. : timer(*this)           // 初始化定时器实例,并指定触发对象。
  4. , interval(1000)                         //初始化显示间隔
  5. , mbox(0)
  6. {
  7.         // TODO: 在此初始化 task_LOOK_TIMER_t 的类成员
  8. }
首先,写法第一次见,应该是表示带了几个参数吗?
其次,对这几个参数的含义不了解:
interval 50 是表示每50个系统周期中断一次吗(已经证实表示50ms)?
mbox 0 是表示初始化邮箱吗(邮箱消息。如果值为 0,表示未获取到消息。)?

2.look::timer_t::do_start  ( uintptr_t  interval )  
这个函数参数的含义,interval = 1 表示多长时间?据我猜测,interval的单位是ms,= 1 表示 1ms (已经证实)。

3.bool task_LOOK_TIMER_t::send_message(int msg)
由Keyboard_t类的dsr()函数调用,是通过消息的方式发送一个参数到task_LOOK_TIMER的邮箱吗?


4.on_signal函数何时被调用,是在定时中产生时被调用吗,还是?这个函数好像是一个被重载的函数?

5.task_LOOK_TIMER是作为一个任务对象创建的。所以,就没有类似于这样的语句:Keyboard_t Key;。

6.用两种方式计时的结果想差很大,有些疑惑,(我知道延时控制并不是精确延时,是与系统负荷有关,但是为什么相差这么大,刷屏很耗资源?):
用两种方式计时,a,定时器计时;b,延时计时。两者的之间的差值如下:
每秒刷屏次数    定时器计数器值    延时计数器值
1        100        86
4        100        60
8        100        42
16        100        27
PS:根据与秒表对比,定时器计数100s与秒表100s基本吻合。验证了interval分辨率为1ms。

最后上传工程代码:

等等,艳照忘记了,白天手机比较给力,让大家养养眼:lol


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| gdmgb520 发表于 2011-10-2 14:40 | 显示全部楼层
编译时可能会提示 count 变量定义的问题。

这是因为定义了一个全局变量,这是C的思维,按照C++,应该定义一个 timer 类的内部成员,然后定义一个public成员函数 get_count(),其他任务通过访问这个成员还是来获取count变量的值。

你也试试:D
 楼主| gdmgb520 发表于 2011-10-2 14:53 | 显示全部楼层

有问题!!

好像不能按楼上的说法做。出现如下编译错误:
  1. Build target 'Release'
  2. compiling led.cpp...
  3. led.cpp: In member function 'void task_led1_t::routine()':
  4. led.cpp(57): error: 'class instantiate::task' has no member named 'get_count'
  5. compiling Timer.cpp...
  6. Timer.cpp: In member function 'void task_LOOK_TIMER_t::routine()':
  7. Timer.cpp(23): warning: unused variable 'msg'
  8. Timer.cpp: At global scope:
  9. Timer.cpp(71): error: no 'long unsigned int task_LOOK_TIMER_t::get_count()' member function declared in class 'task_LOOK_TIMER_t'
  10. Target not created
主要代码如下:
led.cpp
  1. #include "led.h"

  2. #define LOOK_H 1

  3. #if LOOK_H == 0
  4. #include "NUC1xx.h"
  5. #include "NUC1xxM051Seriescfg.h"
  6. #else
  7. #define __HAVE_GPIO
  8. #include <nuc120re3an.h>
  9. using namespace nuvoton;
  10. #endif
  11.                           
  12. #include "tft.h"
  13. #include "Timer.h"

  14. task_tft_t tftObj;                //创建tft对象

  15. //-------------------------------------------------------------------------------------------------------------------------
  16. //               
  17. //-------------------------------------------------------------------------------------------------------------------------
  18. // 任务类 task_led_t 的例程
  19. void task_led1_t::routine()
  20. {
  21.         // TODO: 在此编写 task_led_t 例程的内容
  22. #define X_DIS                        9        //显示信息的位置
  23. #define Y_DIS                        7
  24. #define        FONT_HEIGHT                19        //行高
  25. #define REFRESH_TIMES        16        //每秒的刷新次数
  26.         unsigned char cnt_i = 0;        //次数计数器,一定次数后cnt加1
  27.         uint32_t cnt = 0;        //时间计数器,延时方式,每1s延时后加一
  28.         unsigned long count = 0;        //时间计数器,定时方式,
  29.         unsigned char str[6] = {0};
  30.         
  31.         tftObj.LCD_Init();
  32. //        test_lcd_mon();
  33.         tftObj.LCD_CLEAR(0,0,240,320);
  34.          while (true) {
  35.                 // TODO: 在此编写 task_led_t 例程的内容
  36.                 tftObj.LCD_Display();

  37.                 cnt_i++;
  38.                 if(cnt_i > (REFRESH_TIMES-1))
  39.                 {
  40.                         cnt_i = 0;
  41.                         cnt++;
  42.                 }

  43.                 str[0] = (unsigned char)(cnt / 10000) + 0x30;
  44.                 str[1] = cnt % 10000 / 1000 + 0x30;
  45.                 str[2] = cnt % 1000  / 100 + 0x30;
  46.                 str[3] = cnt % 100   / 10 + 0x30;
  47.                 str[4] = (unsigned char)(cnt % 10) + 0x30;
  48.                 tftObj.LCD_ShowString(X_DIS,Y_DIS,"Running Time:");
  49.                 tftObj.LCD_ShowNumStr(X_DIS+81,Y_DIS-2,str);

  50.                 count =  task_LOOK_TIMER.get_count();
  51.                 str[0] = (unsigned char)(count / 10000) + 0x30;
  52.                 str[1] = count % 10000 / 1000 + 0x30;
  53.                 str[2] = count % 1000  / 100 + 0x30;
  54.                 str[3] = count % 100   / 10 + 0x30;
  55.                 str[4] = (unsigned char)(count % 10) + 0x30;
  56.                 tftObj.LCD_ShowString(X_DIS,Y_DIS+FONT_HEIGHT,"Timer Time:");
  57.                 tftObj.LCD_ShowNumStr(X_DIS+81,Y_DIS-2+FONT_HEIGHT,str);

  58.                 delay(LOOK_TICKS_PER_SEC / REFRESH_TIMES);         //每秒刷新屏幕10次
  59.          }
  60. }


  61. #ifdef LOOK_SCHEDULING_PRIORITY
  62. instantiate::task<task_led1_t, LOOK_STACK_SIZE> task_led1(0);
  63. instantiate::task<task_LOOK_TIMER_t, LOOK_STACK_SIZE> task_LOOK_TIMER(0);
  64. #else
  65. instantiate::task<task_led1_t, LOOK_STACK_SIZE> task_led1;
  66. instantiate::task<task_LOOK_TIMER_t, LOOK_STACK_SIZE> task_LOOK_TIMER;
  67. #endif
2.Timer.h
  1. #ifndef __LOOK_TIMER_H
  2. #define __LOOK_TIMER_H

  3. #include "look_config.h"
  4. #include <look.h>
  5. //#include <instantiate>

  6. //extern unsigned int count;

  7. // 任务类 task_LOOK_TIMER_t 的定义
  8. class task_LOOK_TIMER_t : public task_t {
  9. public:
  10.         __INLINE__ task_LOOK_TIMER_t();        // 构造函数
  11.     void on_signal(void* addr, uintptr_t signal);    // 定义on_signal()        
  12.         bool send_message(int msg);
  13.         unsigned long get_count(void);
  14. protected:
  15.         void routine();                // 任务例程
  16. private:
  17.         timer_t timer;
  18.         int interval;
  19.         mbox_t<int> mbox;
  20.         unsigned long count;
  21. };

  22. // 任务类 LOOK_TIMER 的构造函数
  23. __INLINE__ task_LOOK_TIMER_t::task_LOOK_TIMER_t()
  24. : timer(*this)           // 初始化定时器实例,并指定触发对象。
  25. , interval(1000)                         //初始化显示间隔
  26. , mbox(0)
  27. {
  28.         // TODO: 在此初始化 task_LOOK_TIMER_t 的类成员
  29. }

  30. extern instantiate::task<task_LOOK_TIMER_t, LOOK_STACK_SIZE> task_LOOK_TIMER;

  31. #endif        // __LOOK_TIMER_H
3.Timer.cpp
  1. #include "Timer.h"

  2. #define LOOK_H 1

  3. #if LOOK_H == 0
  4. #include "NUC1xx.h"
  5. #include "NUC1xxM051Seriescfg.h"
  6. #else
  7. #define __HAVE_GPIO
  8. #include <nuc120re3an.h>
  9. using namespace nuvoton;
  10. #endif



  11. // 任务类 task_LOOK_TIMER_t 的例程
  12. void task_LOOK_TIMER_t::routine()
  13. {
  14.         // TODO: 在此编写 task_LOOK_TIMER_t 例程的内容
  15.         timer.start(interval);       //定时器
  16.         while (true) {
  17.                 // TODO: 在此编写 task_LOOK_TIMER_t 例程的内容
  18.                 int msg = mbox.get();                                        // 等待邮箱消息
  19. //                if (msg != 0)
  20. //                {
  21. //                        if ((msg + interval) > 0) {//间隔为0非法,不响
  22. //                                interval += msg;        
  23. //#if LOOK_H == 0
  24. //                                GPIOBs.DMASK.Bits.Pin10 = 0;
  25. //#else
  26. //                                GPIOB.DMASK().DMASK10(0);
  27. //#endif
  28. //                                msg = (msg > 0) ? 1 : 2;//+ 响1声,- 响2声
  29. //                                for (int i = 0; i < (msg * 2); i ++){
  30. //#if LOOK_H == 0
  31. //                                  GPIOBs.DOUT.Bits.Pin10 ^= 1;//蜂鸣器响PB10=1,不响PB10=0
  32. //#else
  33. //                                  GPIOB.DOUT().DOUT10 ^= 1;
  34. //#endif
  35. //                                  delay(LOOK_TICKS_PER_SEC / 20);
  36. //                                }
  37. //#if LOOK_H == 0
  38. //                                GPIOBs.DOUT.Bits.Pin10 = 0;
  39. //#else
  40. //                                GPIOB.DOUT().DOUT10(0);
  41. //#endif
  42. //                        }
  43. //                }
  44.         }
  45. }

  46. void task_LOOK_TIMER_t:n_signal(void* addr, uintptr_t signal)
  47. {
  48.         if (addr == &timer) {
  49.                 timer.do_start(interval);       // 重置定时器
  50.                 // 处理定时器事务
  51.                 count ++;
  52.         }
  53.         else {
  54.                 task_t:n_signal(addr, signal);
  55.         }

  56. }

  57. bool task_LOOK_TIMER_t::send_message(int msg)
  58. {
  59.         return mbox.do_tryput(msg);                //发送消息
  60.         
  61. }

  62. unsigned long task_LOOK_TIMER_t::get_count(void)
  63. {
  64.         return count;
  65. }
还望大家指导。
nixianmin 发表于 2011-10-2 15:37 | 显示全部楼层
本帖最后由 nixianmin 于 2011-10-2 15:55 编辑

顶,不错,timer_t我还没学呢,先看看
1、第一个问题我在C++看过是用来初始化类的变量成员的,
你可以找找那个类里面是不是定一个那几个变量成员
4、上次和lee老师聊谈到过on_signal()这函数,不过还是有点晕,
我简单的说下老师和我说的:只有timer类用到了on_signal(),
但用户程序也可以使用on_signal()来传递一些简单的消息,
调度器也有on_signal(),当时间片到时,timer就会触发,
调度器的on_signal()就会被调用。调度器只需在on_signal()处理中,切换任务即可。

根据上面老师说的话应该不难理解,on_signal是在timer对象时间到后被调用的,
用户也可以自己写on_signal()的内容,在调度器和任务里我们都能看到on_signal()这个虚函数

对这函数我也有点迷糊,希望老师再指点下
上传下上次和老师的聊天记录:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
nixianmin 发表于 2011-10-2 15:52 | 显示全部楼层
看了这个例子我可能知道了,看下面这个任务类
下面是一个邮箱,一个任务对象,通过timer对象可以设置定时
的时间,当时间到时会自动调用程序里的所有on_signal()函数,
怎么能调用所有的我不知道不过可能用一个look::signal_sink_t的
对像指针,并通过on_signal()里的addr == &timer这句来判断
是否是LOOK_TIMER_t类中的timer对像产生的。

那个send_message函数就是用函数方式将消息存到类的邮箱
  1. class task_LOOK_TIMER_t : public task_t {
  2. public:
  3.         __INLINE__ task_LOOK_TIMER_t();        // 构造函数
  4.     void on_signal(void* addr, uintptr_t signal);    // 定义on_signal()       
  5.         bool send_message(int msg);
  6. protected:
  7.         void routine();                // 任务例程
  8. private:
  9.         timer_t timer;
  10.         int interval;
  11.         mbox_t mbox;
  12. };
  13. void task_LOOK_TIMER_t::on_signal(void* addr, uintptr_t signal)
  14. {
  15.         if (addr == &timer) {
  16.                 timer.do_start(interval);       // 重置定时器
  17.                 // 处理定时器事务
  18.                 count ++;
  19.         }
  20.         else {
  21.                 task_t::on_signal(addr, signal);
  22.         }

  23. }
差不多,期待老师详细的解答,如果错了那就误人子弟了
 楼主| gdmgb520 发表于 2011-10-2 16:12 | 显示全部楼层
4# nixianmin

在楼上的提醒下,我找到了问题1的答案,其实上次看过,只是又忘记了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
weshiluwei6 发表于 2011-10-9 21:55 | 显示全部楼层
高手如云啊  这个屏几个钱
abin0415 发表于 2012-4-29 02:05 | 显示全部楼层
多谢LZ共享
 楼主| gdmgb520 发表于 2012-4-30 15:58 | 显示全部楼层
8# abin0415

过去这么久了,能帮到别人真是很高兴啊
mcs8098 发表于 2012-8-1 21:25 | 显示全部楼层
:victory:
mcs8098 发表于 2012-8-1 21:26 | 显示全部楼层
:victory:
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:了解新东西才知道自己的不足。 www.elecbench.com

67

主题

452

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部