[LOOK] LOOK+红杏头文件 学习第四帖:中断抽象类UART0收发练习

[复制链接]
 楼主| Swallow_0322 发表于 2011-6-12 10:02 | 显示全部楼层 |阅读模式
本帖最后由 hotpower 于 2011-6-19 01:24 编辑

------------------------------2011-06-09------------------------------
LOOK实现四个小任务:
① task_led_t: 助学板上四个LED小灯轮流点亮,有两种显示模式,方式1为LED1--->LED2--->LED3--->LED4--->LED1循环,方式2为LED4--->LED3--->LED2--->LED1--->LED4循环,初始化为方式2;
② task_key_t: 助学板上KEY2通过查询的方式判断按下调整LED的循环方式;
③ 继承于interrupt_t的中断抽象类Key_t: 助学板上KEY1设置为下降沿中断,中断滞后服务函数内置位蜂鸣器鸣叫事件标志;
④ task_beep_t: 助学板上蜂鸣器响3声,该任务由KEY1同步。

初始化设置:时钟配置为 XTL12M_EN: 外部 4~24MHz 晶振使能
                            GPA2~5 GPB10 配置为输出模式
                            GPB14~15     配置为输入模式
                 CPU时钟频率为12MHz


关于flag_t:
ANY是wait()事件标志的集合中,任何一个事件到达都可以唤醒任务,相当于“或”运算;
ALL是wait()事件标志的集合中,所有事件全部到达时才能唤醒任务,相当于“与”运算;
当期待的事件标志只有一位时,无所谓ANY,ALL。
KEEP表示到达的事件标志,在唤醒了等待的任务后,该事件不消失(可以继续唤醒其它任务);
COSUME表示到达的事件标志,在唤醒了等待的任务后,该事件消失。
------------------------------2011-06-12------------------------------

在原基础上作如下调整:
① 取消中断抽象类任务Key_t,该任务实现的功能整合至一般任务类task_key_t中的key_read中;
② 增加中断抽象类任务uart0_t,该任务主要实现UART输出和接收功能,接收到字符'1'为同步蜂鸣器响3次任务,接收到字符'2'实现与KEY2按下相同功能;(参考Lee老师DS18B20的例程)
③ task_beep_t中增加蜂鸣器响之前发送字符串"Buzzer rang three times!\n"。

初始化设置: PB.0选择多功能输入RXD0 PB.1选择多功能输入TXD0
            UART时钟选择外部12MHZ,并使能UART0时钟


源程序:
led.h
  1. #include "look_config.h"
  2. #include <look.h>
  3. #include <instantiate>

  4. #define KEY_NO_DOWN ((1<<14)|(1<<15)) //无按键按下时管脚PIN值

  5. // 任务类 task_led_t 的定义
  6. class task_led_t : public task_t {
  7. public:
  8. task_led_t() __OPT_ATTR__; // 构造函数
  9. protected:
  10. void routine(); // 任务例程
  11. };
  12. // 任务类 task_led_t 的构造函数
  13. __OPT_INLINE__ task_led_t::task_led_t()
  14. {
  15. // TODO: 在此初始化 task_led_t 的类成员
  16. }
  17. // 任务类 task_key_t 的定义
  18. class task_key_t : public task_t {
  19. public:
  20. task_key_t() __OPT_ATTR__; // 构造函数
  21. int32_t key_read() __OPT_ATTR__;
  22. protected:
  23. void routine(); // 任务例程
  24. };

  25. // 任务类 task_key_t 的构造函数
  26. __OPT_INLINE__ task_key_t::task_key_t()
  27. {
  28. // TODO: 在此初始化 task_led_t 的类成员
  29. }
  30. // 任务类 task_beep_t 的定义
  31. class task_beep_t : public task_t {
  32. public:
  33. task_beep_t() __OPT_ATTR__; // 构造函数
  34. protected:
  35. void routine(); // 任务例程
  36. };

  37. // 任务类 task_key_t 的构造函数
  38. __OPT_INLINE__ task_beep_t::task_beep_t()
  39. {
  40. // TODO: 在此初始化 task_led_t 的类成员
  41. }

  42. extern instantiate::task<task_led_t, LOOK_STACK_SIZE> task_led;
  43. extern instantiate::task<task_key_t, LOOK_STACK_SIZE> task_key;
  44. extern instantiate::task<task_beep_t, LOOK_STACK_SIZE> task_beep;
led.cpp
  1. #include "NUC1xx.h"
  2. #include "NUC1xxM051Seriescfg.h"
  3. #include "led.h"

  4. flag_t Flag(0); //位0为LED闪烁模式 位1为KEY1控制蜂鸣器任务同步标志 位2为UART通信控制蜂鸣器任务同步标志

  5. // uart0_t 类为应用层提供了简单的 uart 同步输出功能及接收功能。
  6. class uart0_t : public interrupt_t {
  7. public:
  8. uart0_t() __OPT_ATTR__; //构造函数
  9. void puts(const char* str); //串口输出函数
  10. protected:
  11. bool isr(int vector); //中断服务例程
  12. void dsr(int vector, uintptr_t count); //中断滞后服务例程
  13. private:
  14. void fillfifo(const char* str); //填充FIFO
  15. private:
  16. const char* buffer; // 输出缓冲区
  17. task_t* task; // 正在输出的任务
  18. };

  19. // uart0 构造函数
  20. __OPT_INLINE__ uart0_t::uart0_t()
  21. {
  22. attach(UART0_IRQn);
  23. vector_t::enable(UART0_IRQn);
  24. SYSs.IPRSTC2.Bits.UART0_RST = 1; //UART0 模块复位
  25. SYSs.IPRSTC2.Bits.UART0_RST = 0; //UART0 模块正常工作
  26. UART0s.FCR.Bits.TFR = 1; //TX 软件复位
  27. UART0s.FCR.Bits.RFR = 1; //RX 软件复位
  28. UART0s.FCR.Bits.RFITL = 0x00; //Rx FIFO中断 (INT_RDA) 触发级别 1位

  29. UART0s.LCR.Bits.SPE = 0; //无校验 奇偶使能位
  30. UART0s.LCR.Bits.EPE = 0; // 0----奇校验 1----偶校验
  31. UART0s.LCR.Bits.PBE = 0;
  32. UART0s.LCR.Bits.WLS = 0b011; //字长度选择 8bits
  33. UART0s.LCR.Bits.NSB = 0; //1位停止位

  34. UART0s.BAUD.Bits.BRD = 0x66; //外部12MHz 115200bps 对波特率分频寄存器的设置波特率分频设置即该句必须放在第一位
  35. UART0s.BAUD.Bits.DIV_X_EN = 1; //使能分频X
  36. UART0s.BAUD.Bits.DIV_X_ONE = 1; //Divider X equal 1

  37. UART0s.IER.Bits.RDA_IEN = 1; //使能接收中断
  38. /*
  39. DIV_X_EN DIV_X_ONE Divider X BRD 波特率公式
  40. Disable 0 B A UART_CLK / [16 * (A+2)]
  41. Enable 0 B A UART_CLK / [(B+1) * (A+2)] , B must >= 8
  42. Enable 1 B A UART_CLK / (A+2), A must >=3
  43. */
  44. }

  45. // uart0 输出
  46. void uart0_t::puts(const char* str)
  47. {
  48. fillfifo(str); // 填充 fifo
  49. UART0s.IER.Bits.THRE_IEN = 1; // 允许发送中断
  50. task = &scheduler.get_current_task();
  51. delay(); // 阻塞任务
  52. }

  53. // uart0 中断服务例程
  54. bool uart0_t::isr(int vector)
  55. {
  56. if (UART0s.ISR.Bits.THRE_INT==1)
  57. {
  58. //UART0发送中断
  59. const char* str = buffer;
  60. if (str == 0) { // 无数据
  61. UART0s.IER.Bits.THRE_IEN = 0; // 禁止发送中断
  62. return true;
  63. }
  64. fillfifo(str); // 填充 fifo
  65. return false;
  66. }
  67. if (UART0s.ISR.Bits.RDA_INT==1)
  68. {
  69. //UART0接收中断
  70. /* Get all the input characters */
  71. while(UART0s.ISR.Bits.RDA_IF)
  72. {
  73. /* Get the character from UART Buffer */
  74. uint8_t Received_Data = UART0s.DATA.Regs;
  75. if (Received_Data=='1')
  76. {
  77. //执行蜂鸣器响3次的任务
  78. Flag.do_set_bits(0b0100);
  79. }
  80. else if (Received_Data=='2')
  81. {
  82. //执行与KEY2相同的动作
  83. int ** = Flag.peek();
  84. if (**&0b01)
  85. Flag.do_mask_bits(~0b01); //清除事件标志 位0
  86. else
  87. Flag.do_set_bits(0b01); //置位事件标志 位0
  88. }
  89. return false;
  90. }
  91. }
  92. return false;
  93. }

  94. // uart0 中断滞后服务例程
  95. // 所有数据发送完成后,dsr() 被调用
  96. void uart0_t::dsr(int vector, uintptr_t count)
  97. {
  98. task->do_wakeup(); // 唤醒任务
  99. }

  100. // uart0 填充 fifo
  101. void uart0_t::fillfifo(const char* str)
  102. {
  103. do {
  104. char ch;
  105. ch = *str++;
  106. if (ch == 0) {
  107. str = 0;
  108. break;
  109. }
  110. UART0s.DATA.Regs = ch;
  111. } while (!UART0s.FSR.Bits.TX_FULL);
  112. buffer = str;
  113. }

  114. uart0_t uart0; // 创建 uart0 对象

  115. // 任务类 task_led_t 的例程
  116. void task_led_t::routine()
  117. {
  118. // TODO: 在此编写 task_led_t 例程的内容
  119. GPIOAs.DMASK.Regs = ~0b111100;
  120. GPIOAs.DOUT.Regs = ~0b100;
  121. while (true)
  122. {
  123. // TODO: 在此编写 task_led_t 例程的内容
  124. uint32_t data = GPIOAs.DOUT.Regs & 0b111100;
  125. int flag = Flag.peek();
  126. if (flag)
  127. {
  128. data <<= 1;
  129. data += data >> 4;
  130. }
  131. else
  132. {
  133. data >>= 1;
  134. data += data << 4;
  135. }
  136. GPIOAs.DOUT.Regs = data;
  137. delay(LOOK_TICKS_PER_SEC);
  138. }
  139. }

  140. // 任务类 task_key_t 的例程
  141. void task_key_t::routine()
  142. {
  143. // TODO: 在此编写 task_led_t 例程的内容
  144. while (true)
  145. {
  146. // TODO: 在此编写 task_led_t 例程的内容
  147. uint32_t Key_Val = key_read();
  148. if ((Key_Val&(1<<14))==0)
  149. {
  150. //KEY2 按下
  151. int ** = Flag.peek();
  152. if (**&0b01)
  153. Flag.mask_bits(~0b01); //清除事件标志 位0
  154. else
  155. Flag.set_bits(0b01); //置位事件标志 位0
  156. }
  157. if ((Key_Val&(1<<15))==0)
  158. {
  159. //KEY1 按下
  160. Flag.do_set_bits(0b010);
  161. }
  162. delay(LOOK_TICKS_PER_SEC/10);
  163. }
  164. }

  165. // 任务类 task_key_t 的成员函数
  166. __OPT_INLINE__ int32_t task_key_t::key_read()
  167. {
  168. uint32_t Key_Tmp = TRUE;
  169. static uint32_t Key_Record = KEY_NO_DOWN; //按键记录
  170. Key_Tmp = GPIOBs.PIN.Regs&KEY_NO_DOWN;
  171. if(Key_Tmp==KEY_NO_DOWN) //无有效按键按下
  172. {
  173. Key_Record = KEY_NO_DOWN; //清除按键记录
  174. return KEY_NO_DOWN; //程序退出
  175. }
  176. if(Key_Record!=Key_Tmp) //为新按键
  177. {
  178. Key_Record = Key_Tmp; //保存本次结果
  179. delay(LOOK_TICKS_PER_SEC/100); //延时去抖动
  180. Key_Tmp = GPIOBs.PIN.Regs&KEY_NO_DOWN;
  181. if(Key_Tmp==Key_Record)
  182. return Key_Tmp;
  183. }
  184. return KEY_NO_DOWN;
  185. }

  186. // 任务类 task_beep_t 的例程
  187. void task_beep_t::routine()
  188. {
  189. // TODO: 在此编写 task_led_t 例程的内容
  190. GPIOBs.DOUT.Bits.Pin10 = 0; //蜂鸣器不响
  191. while (true)
  192. {
  193. // TODO: 在此编写 task_led_t 例程的内容
  194. int flag = Flag.wait(0b110, flag_t::ANY_CONSUME);
  195. if (flag)
  196. {
  197. uart0.puts("Buzzer rang three times!\n");
  198. for (uint32_t i = 0; i < 6; i ++)
  199. {
  200. //蜂鸣器响三次
  201. GPIOBs.DOUT.Bits.Pin10 ^= 1; //蜂鸣器响PB10=1,不响PB10=0
  202. delay(LOOK_TICKS_PER_SEC); //断续间隔
  203. }
  204. }
  205. }
  206. }

  207. #ifdef LOOK_SCHEDULING_PRIORITY
  208. instantiate::task<task_key_t, LOOK_STACK_SIZE> task_key(0);
  209. instantiate::task<task_beep_t, LOOK_STACK_SIZE> task_beep(1);
  210. instantiate::task<task_led_t, LOOK_STACK_SIZE> task_led(2);
  211. #else
  212. instantiate::task<task_key_t, LOOK_STACK_SIZE> task_key;
  213. instantiate::task<task_beep_t, LOOK_STACK_SIZE> task_beep;
  214. instantiate::task<task_led_t, LOOK_STACK_SIZE> task_led;
  215. #endif
 楼主| Swallow_0322 发表于 2011-6-12 10:36 | 显示全部楼层
本帖最后由 Swallow_0322 于 2011-6-12 10:37 编辑

呵呵!现在M0的学习气氛好淡,自己占沙发并在此预报下一贴目标,作为对自己的监督和鞭策!
uart收到某命令后以启动AD转换任务(此时使用信号灯同步任务),然后uart发送AD转换结果(此时会涉及到互斥信号灯),调度算法使用固定优先级
hotpower 发表于 2011-6-12 20:03 | 显示全部楼层
好!俺在路上回家看。
刚与吴旭光教授和牛博士谈了look和ucos。
 楼主| Swallow_0322 发表于 2011-6-12 20:19 | 显示全部楼层
什么结果?等大叔好消息!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:播种一种行为,收获一种习惯;播种一种习惯,收获一种性格;播种一种性格,收获一种人生!

121

主题

1393

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部
个人签名:播种一种行为,收获一种习惯;播种一种习惯,收获一种性格;播种一种性格,收获一种人生!

121

主题

1393

帖子

4

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