[LOOK] 基于 LOOK 系统的助学板 DS18B20 示例

[复制链接]
 楼主| john_lee 发表于 2011-4-3 22:25 | 显示全部楼层 |阅读模式
本帖最后由 hotpower 于 2011-5-23 19:04 编辑

这是一个基于LOOK系统的助学板示例,展示了如何定义任务类与中断类,如何创建任务类实例及中断类实例,如何在任务例程及中断例程中访问同步对象(信号灯、邮箱)。
示例涉及到的外设有:UART0, UART1, GPIO。
运行过程:当用户按 KEY1 时,程序通过 UART1 读取 DS18B20 的温度值并转换为文本信息发送到 UART0。按 KEY2 时,将读取 DS18B20 的 ROM 信息并转换为文本发送到 UART0。

  1. #include "nuc1xx.h"
  2. #include "NUC1xxM051SeriesCfg.h"
  3. #include <look.h>
  4. #include <look/instantiate>
  5. LOOK_HWINIT()
  6. {
  7.     // 初始化系统时钟
  8.     UNLOCKREG(0);                           // 解锁
  9.     SYSCLKs.PWRCON.Bits.XTL12M_EN = 1;      // 外部晶振使能
  10.     volatile uintptr_t n = 10000;
  11.     while (--n);                            // 延时等待晶振稳定
  12.     SYSCLKs.PLLCON.Regs &= ~((1 << SYSCLK_PLLCON_PD)
  13.                             | (1 << SYSCLK_PLLCON_OE));     // PLL输出使能
  14.     n = 10000;
  15.     while (--n);                            // 延时等待PLL稳定
  16.     SYSCLKs.CLKSEL0.Bits.HCLK_S = 2;        // 选择CPU时钟为PLL
  17.     SYSCLKs.CLKSEL1.Bits.UART_S = 0;        // 选择UART时钟为外部晶振
  18.     SYSCLKs.APBCLK.Regs = (1 << SYSCLK_APBCLK_UART0_EN)     // UART0时钟使能
  19.                         | (1 << SYSCLK_APBCLK_UART1_EN);    // UART1时钟使能
  20.     // 防抖设置
  21.     AHBs.AHB_GPIO.DBNCECON.Regs = (7 << GPIO_DBNCECON_DBCLKSEL)
  22.                                 | (1 << GPIO_DBNCECON_DBCLKSRC)
  23.                                 | (1 << GPIO_DBNCECON_ICLK_ON);
  24.     // 关闭蜂鸣器
  25.     GPIOBs.PMD.Bits.PMD10 = GPIO_PMD_OUTPUT;
  26.     GPIOBs.DOUT.Bits.Pin10 = 0;
  27. }
  28. // owou_t 类为应用层提供了1-wire总线的部分操作方法(成员函数),并且封装了一些操作内部使用的数据。
  29. class owou_t : public interrupt_t {
  30. public:
  31.     owou_t() __OPT_ATTR__;
  32.     bool reset();
  33.     int read(uintptr_t bits = 8) __OPT_ATTR__;
  34.     int write(uintptr_t data, uintptr_t bits = 8) __OPT_ATTR__;
  35. protected:
  36.     bool isr(int vector);
  37.     void dsr(int vector, uintptr_t count);
  38.     int touch(uintptr_t data, uintptr_t bits);
  39. private:
  40.     sem_t sem;              // 信号灯为 1-wire 操作提供同步
  41.     uint8_t in_data;        // 从 1-wire 总线上读出的数据。
  42.     uint8_t out_data;       // 要写到 1-wire 总线上的数据,有效的位数由 op_count 设定。
  43.     uint8_t op_count;       // 定义域:1 <= x <= 8:out_data 的有效数据位。
  44.                             // 0x80:表示此次操作为 1-wire 总线复位。
  45. };
  46. // owou_t 构造函数
  47. __OPT_INLINE__ owou_t:wou_t()
  48. : sem(0)
  49. {
  50.     SYSs.GPBMFP.Regs |= (1 << GCR_GPBMFP_UART1_RX)
  51.                         | (1 << GCR_GPBMFP_UART1_TX);       // 设置 UART1 引脚功能
  52.     attach(UART1_IRQn);                                     // 挂接中断对象
  53.     vector_t::enable(UART1_IRQn);                           // 允许 UART1_IRQn
  54. }
  55. // 1-wire 复位操作
  56. bool owou_t::reset()
  57. {
  58.     op_count = 0x80;                                        // 设置 1-wire 总线操作为“复位”
  59.     // 设置 UART1 参数,以产生合适的 1-wire 总线复位操作时序。
  60.     SYSs.IPRSTC2.Bits.UART1_RST = 1;
  61.     SYSs.IPRSTC2.Bits.UART1_RST = 0;
  62.     UART1s.FCR.Regs |= (1 << UART_FCR_TFR) | (1 << UART_FCR_RFR);
  63.     UART1s.LCR.Regs = 3 << UART_LCR_WLS;                    // 设置线控
  64.     UART1s.IER.Regs = 1 << UART_IER_RDA_IEN;                // 允许接收中断
  65.     UART1s.BAUD.Regs = (0x4e0 << UART_BAUD_BRD)
  66.                         | (1 << UART_BAUD_DIV_X_ONE)
  67.                         | (1 << UART_BAUD_DIV_X_EN);        // 波特率 = 9600
  68.     UART1s.DATA.Regs = 0xf0;                                // 发出“复位”信号
  69.     if (sem.wait(LOOK_TICKS_PER_SEC / 20)) {                // 等待“复位”应答
  70.         if (in_data != 0xf0) {                              // “复位”应答出现
  71.             // 收到复位应答后,重新设置 UART1 参数,用以产生合适的 1-wire 总线读写操作时序。
  72.             SYSs.IPRSTC2.Bits.UART1_RST = 1;
  73.             SYSs.IPRSTC2.Bits.UART1_RST = 0;
  74.             UART1s.FCR.Regs |= (1 << UART_FCR_TFR) | (1 << UART_FCR_RFR);
  75.             UART1s.LCR.Regs = 3 << UART_LCR_WLS;
  76.             UART1s.IER.Regs = 1 << UART_IER_RDA_IEN;
  77.             UART1s.BAUD.Regs = (0x66 << UART_BAUD_BRD)
  78.                                 | (1 << UART_BAUD_DIV_X_ONE)
  79.                                 | (1 << UART_BAUD_DIV_X_EN);    // 波特率 = 115200
  80.             return true;
  81.         }
  82.     }
  83.     return false;
  84. }
  85. // 1-wire 读操作
  86. // 参数:
  87. //      bits:需要读出的数据位数。定义域:1 <= x <= 8
  88. // 返回:
  89. //      读到的数据。
  90. __OPT_INLINE__ int owou_t::read(uintptr_t bits)
  91. {
  92.     int data = touch(0xff, bits);
  93.     if (bits < 8)
  94.         data >>= 8 - bits;
  95.     return data;
  96. }
  97. // 1-wire 写操作
  98. // 参数:
  99. //      data: 需要写到 1-wire 总线的数据。
  100. //      bits:数据位数。定义域:1 <= x <= 8
  101. __OPT_INLINE__ int owou_t::write(uintptr_t data, uintptr_t bits)
  102. {
  103.     return touch(data, bits);
  104. }
  105. // 1-wire 中断服务例程
  106. // 当复位操作完成或读写1位完成后,中断发生。
  107. bool owou_t::isr(int vector)
  108. {
  109.     uintptr_t data = UART1s.DATA.Regs;
  110.     if ((op_count & 0x80) != 0) {       // 复位操作
  111.         in_data = data;                 // 保存接收的数据
  112.     } else {                            // 读写操作
  113.         in_data = ((data << 8) + in_data) >> 1; // 组合读出的数据
  114.         uintptr_t count = op_count;
  115.         if (--count != 0) {
  116.             op_count = count;
  117.             UART1s.DATA.Regs = 0 - (out_data & 1);  // 输出 out_data 最低位(扩展为字节)。
  118.             out_data >>= 1;
  119.             return false;
  120.         }                              
  121.     }
  122.     return true;
  123. }
  124. // 1-wire 中断滞后服务例程
  125. // 当 isr() 返回 true 后(复位操作完成或所有的数据位读写操作完成),dsr() 被调用。
  126. void owou_t::dsr(int vector, uintptr_t count)
  127. {
  128.     sem.do_post();          // 释放信号灯资源。
  129. }
  130. // 1-wire 读写例程
  131. int owou_t::touch(uintptr_t data, uintptr_t bits)
  132. {
  133.     in_data = 0;
  134.     out_data = data >> 1;
  135.     op_count = bits;
  136.     UART1s.DATA.Regs = 0 - (data & 1);          // 写首位
  137.     if (sem.wait(LOOK_TICKS_PER_SEC / 20))      // 等待剩余数据位全部完成
  138.         return in_data;
  139.     return -1;
  140. }
  141. owou_t owou;                // 创建 1-wire 对象
  142. // uart0_t 类为应用层提供了简单的 uart 同步输出功能。
  143. class uart0_t : public interrupt_t {
  144. public:
  145.     uart0_t() __OPT_ATTR__;
  146.     void puts(const char* str);
  147. protected:
  148.     bool isr(int vector);
  149.     void dsr(int vector, uintptr_t count);
  150. private:
  151.     void fillfifo(const char* str);
  152. private:
  153.     const char* buffer;             // 输出缓冲区
  154.     task_t* task;                   // 正在输出的任务
  155. };
  156. // uart0 构造函数
  157. __OPT_INLINE__ uart0_t::uart0_t()
  158. {
  159.     SYSs.GPBMFP.Regs |= (1 << GCR_GPBMFP_UART0_RX) | (1 << GCR_GPBMFP_UART0_TX);
  160.     attach(UART0_IRQn);
  161.     vector_t::enable(UART0_IRQn);
  162.     SYSs.IPRSTC2.Bits.UART0_RST = 1;
  163.     SYSs.IPRSTC2.Bits.UART0_RST = 0;
  164.     UART0s.FCR.Regs |= (1 << UART_FCR_TFR) | (1 << UART_FCR_RFR);
  165.     UART0s.LCR.Regs = 3 << UART_LCR_WLS;                        // 8bits
  166.     UART0s.BAUD.Regs = (0x66 << UART_BAUD_BRD)
  167.                         | (1 << UART_BAUD_DIV_X_ONE)
  168.                         | (1 << UART_BAUD_DIV_X_EN);            // 115200
  169. }
  170. // uart0 输出
  171. void uart0_t::puts(const char* str)
  172. {
  173.     fillfifo(str);                  // 填充 fifo
  174.     UART0s.IER.Bits.THRE_IEN = 1;   // 允许发送中断
  175.     task = &scheduler.get_current_task();
  176.     delay();                        // 阻塞任务
  177. }
  178. // uart0 中断服务例程
  179. bool uart0_t::isr(int vector)
  180. {
  181.     const char* str = buffer;
  182.     if (str == 0) {                     // 无数据
  183.         UART0s.IER.Bits.THRE_IEN = 0;   // 禁止发送中断
  184.         return true;
  185.     }
  186.     fillfifo(str);                      // 填充 fifo
  187.     return false;
  188. }
  189. // uart0 中断滞后服务例程
  190. // 所有数据发送完成后,dsr() 被调用
  191. void uart0_t::dsr(int vector, uintptr_t count)
  192. {
  193.     task->do_wakeup();              // 唤醒任务
  194. }
  195. // uart0 填充 fifo
  196. void uart0_t::fillfifo(const char* str)
  197. {
  198.     do {
  199.         char ch;
  200.         ch = *str++;
  201.         if (ch == 0) {
  202.             str = 0;
  203.             break;
  204.         }
  205.         UART0s.DATA.Regs = ch;
  206.     } while (!UART0s.FSR.Bits.TX_FULL);
  207.     buffer = str;
  208. }
  209. uart0_t uart0;              // 创建 uart0 对象
  210. mbox_t<int> mbox(0);        // 创建 int 型邮箱,初值 0
  211. // 主任务
  212. class task_main_t : public task_t {
  213. public:
  214.     task_main_t() __OPT_ATTR__;
  215. protected:
  216.     void routine() __attribute__((noreturn));
  217. private:
  218.     uint8_t buffer[12];         // 1-wire 输入数据缓冲
  219.     char str[28];               // uart0 输出数据缓冲
  220. };
  221. __OPT_INLINE__ task_main_t::task_main_t()
  222. {
  223. }
  224. // 主任务例程
  225. void task_main_t::routine()
  226. {
  227.     while (true) {
  228.         int msg = mbox.get();                   // 等待邮箱消息
  229.         if (msg != 0) {
  230.             if (owou.reset()) {
  231.                 do {
  232.                     int n;
  233.                     if (msg == 1) {             // 消息 1,读 ds18b20 ROM
  234.                         owou.write(0x33);
  235.                         n = 8;                  // 读 8 字节数据
  236.                     } else {
  237.                         owou.write(0xcc);
  238.                         owou.write(0x44);
  239.                         delay(LOOK_TICKS_PER_SEC * 0.75);
  240.                         if (!owou.reset()) {
  241.                             uart0.puts("reset error\n");
  242.                             break;
  243.                         }
  244.                         owou.write(0xcc);
  245.                         owou.write(0xbe);
  246.                         n = 9;                  // 读 9 字节数据
  247.                     }
  248.                     // 读数据并进行 crc 校验
  249.                     uintptr_t crc = 0;
  250.                     int i = 0;
  251.                     do {
  252.                         int data = owou.read();
  253.                         buffer = data;
  254.                         crc ^= data;
  255.                         for (int x = 0; x < 8; x++) {
  256.                             uintptr_t tmp = crc;
  257.                             crc >>= 1;
  258.                             if (tmp & 1)
  259.                                 crc ^= 0x8c;
  260.                         }
  261.                     } while (++i < n);
  262.                     if (crc == 0) {             // crc 正确
  263.                         char* p;
  264.                         if (msg == 1) {         // 消息 1,读 ds18b20 ROM
  265.                             // 转换并输出 serial number 信息到 uart0
  266.                             uart0.puts("serial number:");
  267.                             p = str;
  268.                             i = 0;
  269.                             do {
  270.                                 *p++ = ' ';
  271.                                 int data = buffer;
  272.                                 int tmp = data >> 4;
  273.                                 if (tmp < 10)
  274.                                     tmp += '0';
  275.                                 else
  276.                                     tmp = tmp - 10 + 'A';
  277.                                 *p++ = tmp;
  278.                                 data &= 0xf;
  279.                                 if (data < 10)
  280.                                     data += '0';
  281.                                 else
  282.                                     data = data - 10 + 'A';
  283.                                 *p++ = data;
  284.                             } while (++i < 8);
  285.                             *p++ = '\n';
  286.                             *p = 0;
  287.                             p = str;
  288.                         } else {                // 消息 2,读 ds18b20 scratch pad
  289.                             // 转换并输出 temperature 信息到 uart0
  290.                             uart0.puts("temperature:");
  291.                             int data = *reinterpret_cast<int16_t*>(&buffer[0]);
  292.                             bool neg = false;
  293.                             if (data < 0) {
  294.                                 data = -data;
  295.                                 neg = true;
  296.                             }
  297.                             p = &str[28];
  298.                             *--p = 0;
  299.                             *--p = '\n';
  300.                             uintptr_t tmp = (data & 0xf) * 625;
  301.                             if (tmp != 0) {
  302.                                 int n = 4;
  303.                                 bool b = false;
  304.                                 do {
  305.                                     uintptr_t rem = tmp;
  306.                                     tmp = tmp * (((1 << 19) + 9) / 10) >> 19;
  307.                                     rem -= tmp * 10;
  308.                                     if (b || rem) {
  309.                                         *--p = '0' + rem;
  310.                                         b = true;
  311.                                     }
  312.                                 } while (--n);
  313.                                 *--p = '.';
  314.                             }
  315.                             data >>= 4;
  316.                             do {
  317.                                 uintptr_t rem = data;
  318.                                 data = data * (((1 << 11) + 9) / 10) >> 11;
  319.                                 rem -= data * 10;
  320.                                 *--p = '0' + rem;
  321.                             } while (data);
  322.                             if (neg)
  323.                                 *--p = '-';
  324.                         }
  325.                         uart0.puts(p);              // 输出信息
  326.                     } else
  327.                         uart0.puts("crc error\n");
  328.                 } while (false);
  329.             } else
  330.                 uart0.puts("reset error\n");
  331.         } else
  332.             uart0.puts("Accident be awakened\n");
  333.     }
  334. }
  335. instantiate::task<task_main_t, 30> task_main;       // 创建主任务对象
  336. // eint_t 类提供了 INT0/INT1 的接口
  337. // 当 INT0/INT1 发生时,对象将发送相应的 int 消息到 mbox。
  338. class eint_t : public interrupt_t {
  339. public:
  340.     eint_t() __OPT_ATTR__;
  341. protected:
  342.     bool isr(int vector);
  343.     void dsr(int vector, uintptr_t count);
  344. };
  345. // eint 构造函数
  346. __OPT_INLINE__ eint_t::eint_t()
  347. {
  348.     attach(EINT0_IRQn);
  349.     attach(EINT1_IRQn);
  350.     GPIOBs.PMD.Bits.PMD14 = GPIO_PMD_INPUT;                 // GPIOB14 设置为输入方式
  351.     GPIOBs.PMD.Bits.PMD15 = GPIO_PMD_INPUT;                 // GPIOB15 设置为输入方式
  352.     SYSs.GPBMFP.Regs |= (1 << GCR_GPBMFP_INT1_SS31)         // 复用 INT1
  353.                         | (1 << GCR_GPBMFP_INT0);           // 复用 INT0
  354.     GPIOBs.DBEN.Regs = (1 << Pin15) | (1 << Pin14);         // 开启防抖
  355.     GPIOBs.IEN.Regs = (1 << Pin15) | (1 << Pin14);          // 开启中断
  356.     vector_t::enable(EINT0_IRQn);
  357.     vector_t::enable(EINT1_IRQn);
  358. }
  359. // eint 中断服务例程
  360. bool eint_t::isr(int vector)
  361. {
  362.     GPIOBs.ISRC.Regs = GPIOBs.ISRC.Regs;            // 清中断 flag
  363.     return true;
  364. }
  365. // eint 中断滞后服务例程
  366. void eint_t::dsr(int vector, uintptr_t count)
  367. {
  368.     mbox.do_tryput(vector == EINT0_IRQn ? 2 : 1);       // 发送消息
  369. }
  370. eint_t eint;                                    // 创建 eint 对象
  371. namespace look {
  372.     sched_t scheduler __attribute__((init_priority(112)));  // 创建调度器
  373.     systick_t systick(48000000 / LOOK_TICKS_PER_SEC);       // 创建系统节拍对象
  374.     // 定义中断向量表
  375.     void (*const vector_t::vectors[])() = {
  376.         stack,                  // 0
  377.         reset,                  // 1
  378.         nmi,                    // 2
  379.         hard_fault,             // 3
  380.         0,                      // 4
  381.         0,                      // 5
  382.         0,                      // 6
  383.         0,                      // 7
  384.         0,                      // 8
  385.         0,                      // 9
  386.         0,                      // 10
  387.         base::sched_t::svcall,  // 11
  388.         0,                      // 12
  389.         0,                      // 13
  390.         base::sched_t::pendsv,  // 14
  391.         vsr,                    // 15, systick
  392.         vsr,                    // IRQ0
  393.         vsr,                    // IRQ1
  394.         vsr,                    // IRQ2
  395.         vsr,                    // IRQ3
  396.         vsr,                    // IRQ4
  397.         vsr,                    // IRQ5
  398.         vsr,                    // IRQ6
  399.         vsr,                    // IRQ7
  400.         vsr,                    // IRQ8
  401.         vsr,                    // IRQ9
  402.         vsr,                    // IRQ10
  403.         vsr,                    // IRQ11
  404.         vsr,                    // IRQ12
  405.         vsr,                    // IRQ13
  406.         vsr,                    // IRQ14
  407.         vsr,                    // IRQ15
  408.         vsr,                    // IRQ16
  409.         vsr,                    // IRQ17
  410.         vsr,                    // IRQ18
  411.         vsr,                    // IRQ19
  412.         vsr,                    // IRQ20
  413.         vsr,                    // IRQ21
  414.         vsr,                    // IRQ22
  415.         vsr,                    // IRQ23
  416.         vsr,                    // IRQ24
  417.         vsr,                    // IRQ25
  418.         vsr,                    // IRQ26
  419.         vsr,                    // IRQ27
  420.         vsr,                    // IRQ28
  421.         vsr,                    // IRQ29
  422.         vsr,                    // IRQ30
  423.         vsr                     // IRQ31
  424.     };
  425.     vector_t vector_t::table[sizeof(vectors) / sizeof(vectors[0]) - 15];
  426. }

评分

参与人数 2威望 +11 收起 理由
hotpower + 10
dong_abc + 1

查看全部评分

murex 发表于 2011-4-3 22:44 | 显示全部楼层
老师的好贴一定要顶
hotpower 发表于 2011-4-3 22:45 | 显示全部楼层
本帖最后由 hotpower 于 2011-5-30 13:29 编辑

给力Look!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

俺运行的图:

本帖子中包含更多资源

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

×
Cube 发表于 2011-4-3 23:08 | 显示全部楼层
拜读中:)
xjm05413 发表于 2011-4-3 23:25 | 显示全部楼层
传说中的Look~~~~~
tear086 发表于 2011-4-4 00:26 | 显示全部楼层
看CPP,好吃力。
 楼主| john_lee 发表于 2011-4-4 02:09 | 显示全部楼层
示例中相当大的一部分都是程序框架,属于定式(可能以后会用wizard自动生成),除开这些后,程序实际上是很简单的。

为了简单起见,示例只用了一个任务,但却展示出了RTOS的大部分元素:任务,中断,同步对象。

以后我会给出更多的示例,逐步展示出LOOK更多的特点,如:多任务调度,信号系统,以及如何扩展LOOK(为LOOK提供用户自己的调度器,抽象任务类和同步对象)等等。
hotpower 发表于 2011-4-4 02:10 | 显示全部楼层
呵呵,要学习优秀的技术
 楼主| john_lee 发表于 2011-4-4 02:28 | 显示全部楼层
程序大概的运行流程:
1、运行LOOK_HWINIT()函数中的代码。
2、运行scheduler构造函数。
     sched_t scheduler __attribute__((init_priority(112)));  // 创建调度器
3、运行各个对象的构造函数(没有固定的顺序):
     systick_t systick(48000000 / LOOK_TICKS_PER_SEC);       // 创建系统节拍对象
     owou_t owou;                // 创建 1-wire 对象
     uart0_t uart0;              // 创建 uart0 对象
     mbox_t<int> mbox(0);        // 创建 int 型邮箱,初值 0
     instantiate::task<task_main_t, 30> task_main;       // 创建主任务对象
     eint_t eint;                                    // 创建 eint 对象
4、运行主任务例程:void task_main_t::routine()

评分

参与人数 1威望 +1 收起 理由
dong_abc + 1

查看全部评分

 楼主| john_lee 发表于 2011-4-4 02:40 | 显示全部楼层
本帖最后由 john_lee 于 2011-4-4 02:53 编辑

使用-Os优化编译连接后的目标文件大小:
ROM占用:3224,其中LOOK系统占用1380
RAM占用:704,其中LOOK系统占用412
hotpower 发表于 2011-4-4 07:23 | 显示全部楼层
希望老师多出例程,早日文档与普及,辛苦了!
Swallow_0322 发表于 2011-4-4 08:10 | 显示全部楼层
传说中的LOOK,现仅止步于羡慕,希望通过老师越来越多的例程,俺也能向它迈入一小步,(*^__^*) 嘻嘻……
高端!:victory:
dong_abc 发表于 2011-4-4 15:13 | 显示全部楼层
好贴!
maxking 发表于 2011-4-4 19:54 | 显示全部楼层
能做出一个在液晶12232显示出来的就好了。
hotpower 发表于 2011-4-5 11:21 | 显示全部楼层
老师已在QQ群(12047788)里讲授LOOK的基本原理和实现。
hotpower 发表于 2011-4-5 11:21 | 显示全部楼层
老师已在QQ群(12047788)里讲授LOOK的基本原理和实现。
plc_avr 发表于 2011-4-8 10:47 | 显示全部楼层
有空时慢慢看........
hotpower 发表于 2011-4-14 17:52 | 显示全部楼层
希望有更多的例程才能有利于普及
 楼主| john_lee 发表于 2011-4-21 21:30 | 显示全部楼层
本帖最后由 john_lee 于 2011-5-16 19:27 编辑

使用 Wizard 后的 简化文件,cpp:
  1. #include "nuc1xx.h"
  2. #include "NUC1xxM051SeriesCfg.h"
  3. #include "task.h"           // 此处需要更改为 Wizard 生成的 “目标文件名.h”
  4. // owou_t 类为应用层提供了1-wire总线的部分操作方法(成员函数),并且封装了一些操作内部使用的数据。
  5. class owou_t : public interrupt_t {
  6. public:
  7.     owou_t() __OPT_ATTR__;
  8.     bool reset();
  9.     int read(uintptr_t bits = 8) __OPT_ATTR__;
  10.     int write(uintptr_t data, uintptr_t bits = 8) __OPT_ATTR__;
  11. protected:
  12.     bool isr(int vector);
  13.     void dsr(int vector, uintptr_t count);
  14.     int touch(uintptr_t data, uintptr_t bits);
  15. private:
  16.     sem_t sem;              // 信号灯为 1-wire 操作提供同步
  17.     uint8_t in_data;        // 从 1-wire 总线上读出的数据。
  18.     uint8_t out_data;       // 要写到 1-wire 总线上的数据,有效的位数由 op_count 设定。
  19.     uint8_t op_count;       // 定义域:1 <= x <= 8:out_data 的有效数据位。
  20.                             // 0x80:表示此次操作为 1-wire 总线复位。
  21. };
  22. // owou_t 构造函数
  23. __OPT_INLINE__ owou_t:wou_t()
  24. : sem(0)
  25. {
  26. //  SYSs.GPBMFP.Regs |= (1 << GCR_GPBMFP_UART1_RX)
  27. //                      | (1 << GCR_GPBMFP_UART1_TX);       // 设置 UART1 引脚功能
  28.     attach(UART1_IRQn);                                     // 挂接中断对象
  29.     vector_t::enable(UART1_IRQn);                           // 允许 UART1_IRQn
  30. }
  31. // 1-wire 复位操作
  32. bool owou_t::reset()
  33. {
  34.     op_count = 0x80;                                        // 设置 1-wire 总线操作为“复位”
  35.     // 设置 UART1 参数,以产生合适的 1-wire 总线复位操作时序。
  36.     SYSs.IPRSTC2.Bits.UART1_RST = 1;
  37.     SYSs.IPRSTC2.Bits.UART1_RST = 0;
  38.     UART1s.FCR.Regs |= (1 << UART_FCR_TFR) | (1 << UART_FCR_RFR);
  39.     UART1s.LCR.Regs = 3 << UART_LCR_WLS;                    // 设置线控
  40.     UART1s.IER.Regs = 1 << UART_IER_RDA_IEN;                // 允许接收中断
  41.     UART1s.BAUD.Regs = (0x4e0 << UART_BAUD_BRD)
  42.                         | (1 << UART_BAUD_DIV_X_ONE)
  43.                         | (1 << UART_BAUD_DIV_X_EN);        // 波特率 = 9600
  44.     UART1s.DATA.Regs = 0xf0;                                // 发出“复位”信号
  45.     if (sem.wait(LOOK_TICKS_PER_SEC / 20)) {                // 等待“复位”应答
  46.         if (in_data != 0xf0) {                              // “复位”应答出现
  47.             // 收到复位应答后,重新设置 UART1 参数,用以产生合适的 1-wire 总线读写操作时序。
  48.             SYSs.IPRSTC2.Bits.UART1_RST = 1;
  49.             SYSs.IPRSTC2.Bits.UART1_RST = 0;
  50.             UART1s.FCR.Regs |= (1 << UART_FCR_TFR) | (1 << UART_FCR_RFR);
  51.             UART1s.LCR.Regs = 3 << UART_LCR_WLS;
  52.             UART1s.IER.Regs = 1 << UART_IER_RDA_IEN;
  53.             UART1s.BAUD.Regs = (0x66 << UART_BAUD_BRD)
  54.                                 | (1 << UART_BAUD_DIV_X_ONE)
  55.                                 | (1 << UART_BAUD_DIV_X_EN);    // 波特率 = 115200
  56.             return true;
  57.         }
  58.     }
  59.     return false;
  60. }
  61. // 1-wire 读操作
  62. // 参数:
  63. //      bits:需要读出的数据位数。定义域:1 <= x <= 8
  64. // 返回:
  65. //      读到的数据。
  66. __OPT_INLINE__ int owou_t::read(uintptr_t bits)
  67. {
  68.     int data = touch(0xff, bits);
  69.     if (bits < 8)
  70.         data >>= 8 - bits;
  71.     return data;
  72. }
  73. // 1-wire 写操作
  74. // 参数:
  75. //      data: 需要写到 1-wire 总线的数据。
  76. //      bits:数据位数。定义域:1 <= x <= 8
  77. __OPT_INLINE__ int owou_t::write(uintptr_t data, uintptr_t bits)
  78. {
  79.     return touch(data, bits);
  80. }
  81. // 1-wire 中断服务例程
  82. // 当复位操作完成或读写1位完成后,中断发生。
  83. bool owou_t::isr(int vector)
  84. {
  85.     uintptr_t data = UART1s.DATA.Regs;
  86.     if ((op_count & 0x80) != 0) {       // 复位操作
  87.         in_data = data;                 // 保存接收的数据
  88.     } else {                            // 读写操作
  89.         in_data = ((data << 8) + in_data) >> 1; // 组合读出的数据
  90.         uintptr_t count = op_count;
  91.         if (--count != 0) {
  92.             op_count = count;
  93.             UART1s.DATA.Regs = 0 - (out_data & 1);  // 输出 out_data 最低位(扩展为字节)。
  94.             out_data >>= 1;
  95.             return false;
  96.         }                              
  97.     }
  98.     return true;
  99. }
  100. // 1-wire 中断滞后服务例程
  101. // 当 isr() 返回 true 后(复位操作完成或所有的数据位读写操作完成),dsr() 被调用。
  102. void owou_t::dsr(int vector, uintptr_t count)
  103. {
  104.     sem.do_post();          // 释放信号灯资源。
  105. }
  106. // 1-wire 读写例程
  107. int owou_t::touch(uintptr_t data, uintptr_t bits)
  108. {
  109.     in_data = 0;
  110.     out_data = data >> 1;
  111.     op_count = bits;
  112.     UART1s.DATA.Regs = 0 - (data & 1);          // 写首位
  113.     if (sem.wait(LOOK_TICKS_PER_SEC / 20))      // 等待剩余数据位全部完成
  114.         return in_data;
  115.     return -1;
  116. }
  117. owou_t owou;                // 创建 1-wire 对象
  118. // uart0_t 类为应用层提供了简单的 uart 同步输出功能。
  119. class uart0_t : public interrupt_t {
  120. public:
  121.     uart0_t() __OPT_ATTR__;
  122.     void puts(const char* str);
  123. protected:
  124.     bool isr(int vector);
  125.     void dsr(int vector, uintptr_t count);
  126. private:
  127.     void fillfifo(const char* str);
  128. private:
  129.     const char* buffer;             // 输出缓冲区
  130.     task_t* task;                   // 正在输出的任务
  131. };
  132. // uart0 构造函数
  133. __OPT_INLINE__ uart0_t::uart0_t()
  134. {
  135. //  SYSs.GPBMFP.Regs |= (1 << GCR_GPBMFP_UART0_RX) | (1 << GCR_GPBMFP_UART0_TX);
  136.     attach(UART0_IRQn);
  137.     vector_t::enable(UART0_IRQn);
  138.     SYSs.IPRSTC2.Bits.UART0_RST = 1;
  139.     SYSs.IPRSTC2.Bits.UART0_RST = 0;
  140.     UART0s.FCR.Regs |= (1 << UART_FCR_TFR) | (1 << UART_FCR_RFR);
  141.     UART0s.LCR.Regs = 3 << UART_LCR_WLS;                        // 8bits
  142.     UART0s.BAUD.Regs = (0x66 << UART_BAUD_BRD)
  143.                         | (1 << UART_BAUD_DIV_X_ONE)
  144.                         | (1 << UART_BAUD_DIV_X_EN);            // 115200
  145. }
  146. // uart0 输出
  147. void uart0_t::puts(const char* str)
  148. {
  149.     fillfifo(str);                  // 填充 fifo
  150.     UART0s.IER.Bits.THRE_IEN = 1;   // 允许发送中断
  151.     task = &scheduler.get_current_task();
  152.     delay();                        // 阻塞任务
  153. }
  154. // uart0 中断服务例程
  155. bool uart0_t::isr(int vector)
  156. {
  157.     const char* str = buffer;
  158.     if (str == 0) {                     // 无数据
  159.         UART0s.IER.Bits.THRE_IEN = 0;   // 禁止发送中断
  160.         return true;
  161.     }
  162.     fillfifo(str);                      // 填充 fifo
  163.     return false;
  164. }
  165. // uart0 中断滞后服务例程
  166. // 所有数据发送完成后,dsr() 被调用
  167. void uart0_t::dsr(int vector, uintptr_t count)
  168. {
  169.     task->do_wakeup();              // 唤醒任务
  170. }
  171. // uart0 填充 fifo
  172. void uart0_t::fillfifo(const char* str)
  173. {
  174.     do {
  175.         char ch;
  176.         ch = *str++;
  177.         if (ch == 0) {
  178.             str = 0;
  179.             break;
  180.         }
  181.         UART0s.DATA.Regs = ch;
  182.     } while (!UART0s.FSR.Bits.TX_FULL);
  183.     buffer = str;
  184. }
  185. uart0_t uart0;              // 创建 uart0 对象
  186. mbox_t<int> mbox(0);        // 创建 int 型邮箱,初值 0
  187. // 主任务例程
  188. void task_main_t::routine()
  189. {
  190.     while (true) {
  191.         int msg = mbox.get();                   // 等待邮箱消息
  192.         if (msg != 0) {
  193.             if (owou.reset()) {
  194.                 do {
  195.                     int n;
  196.                     if (msg == 1) {             // 消息 1,读 ds18b20 ROM
  197.                         owou.write(0x33);
  198.                         n = 8;                  // 读 8 字节数据
  199.                     } else {
  200.                         owou.write(0xcc);
  201.                         owou.write(0x44);
  202.                         delay(LOOK_TICKS_PER_SEC * 0.75);
  203.                         if (!owou.reset()) {
  204.                             uart0.puts("reset error\n");
  205.                             break;
  206.                         }
  207.                         owou.write(0xcc);
  208.                         owou.write(0xbe);
  209.                         n = 9;                  // 读 9 字节数据
  210.                     }
  211.                     // 读数据并进行 crc 校验
  212.                     uintptr_t crc = 0;
  213.                     int i = 0;
  214.                     do {
  215.                         int data = owou.read();
  216.                         buffer = data;
  217.                         crc ^= data;
  218.                         for (int x = 0; x < 8; x++) {
  219.                             uintptr_t tmp = crc;
  220.                             crc >>= 1;
  221.                             if (tmp & 1)
  222.                                 crc ^= 0x8c;
  223.                         }
  224.                     } while (++i < n);
  225.                     if (crc == 0) {             // crc 正确
  226.                         char* p;
  227.                         if (msg == 1) {         // 消息 1,读 ds18b20 ROM
  228.                             // 转换并输出 serial number 信息到 uart0
  229.                             uart0.puts("serial number:");
  230.                             p = str;
  231.                             i = 0;
  232.                             do {
  233.                                 *p++ = ' ';
  234.                                 int data = buffer;
  235.                                 int tmp = data >> 4;
  236.                                 if (tmp < 10)
  237.                                     tmp += '0';
  238.                                 else
  239.                                     tmp = tmp - 10 + 'A';
  240.                                 *p++ = tmp;
  241.                                 data &= 0xf;
  242.                                 if (data < 10)
  243.                                     data += '0';
  244.                                 else
  245.                                     data = data - 10 + 'A';
  246.                                 *p++ = data;
  247.                             } while (++i < 8);
  248.                             *p++ = '\n';
  249.                             *p = 0;
  250.                             p = str;
  251.                         } else {                // 消息 2,读 ds18b20 scratch pad
  252.                             // 转换并输出 temperature 信息到 uart0
  253.                             uart0.puts("temperature:");
  254.                             int data = *reinterpret_cast<int16_t*>(&buffer[0]);
  255.                             bool neg = false;
  256.                             if (data < 0) {
  257.                                 data = -data;
  258.                                 neg = true;
  259.                             }
  260.                             p = &str[28];
  261.                             *--p = 0;
  262.                             *--p = '\n';
  263.                             uintptr_t tmp = (data & 0xf) * 625;
  264.                             if (tmp != 0) {
  265.                                 int n = 4;
  266.                                 bool b = false;
  267.                                 do {
  268.                                     uintptr_t rem = tmp;
  269.                                     tmp = tmp * (((1 << 19) + 9) / 10) >> 19;
  270.                                     rem -= tmp * 10;
  271.                                     if (b || rem) {
  272.                                         *--p = '0' + rem;
  273.                                         b = true;
  274.                                     }
  275.                                 } while (--n);
  276.                                 *--p = '.';
  277.                             }
  278.                             data >>= 4;
  279.                             do {
  280.                                 uintptr_t rem = data;
  281.                                 data = data * (((1 << 11) + 9) / 10) >> 11;
  282.                                 rem -= data * 10;
  283.                                 *--p = '0' + rem;
  284.                             } while (data);
  285.                             if (neg)
  286.                                 *--p = '-';
  287.                         }
  288.                         uart0.puts(p);              // 输出信息
  289.                     } else
  290.                         uart0.puts("crc error\n");
  291.                 } while (false);
  292.             } else
  293.                 uart0.puts("reset error\n");
  294.         } else
  295.             uart0.puts("Accident be awakened\n");
  296.     }
  297. }
  298. instantiate::task<task_main_t, LOOK_STACK_SIZE> task_main;      // 创建主任务对象
  299. // eint_t 类提供了 INT0/INT1 的接口
  300. // 当 INT0/INT1 发生时,对象将发送相应的 int 消息到 mbox。
  301. class eint_t : public interrupt_t {
  302. public:
  303.     eint_t() __OPT_ATTR__;
  304. protected:
  305.     bool isr(int vector);
  306.     void dsr(int vector, uintptr_t count);
  307. };
  308. // eint 构造函数
  309. __OPT_INLINE__ eint_t::eint_t()
  310. {
  311.     attach(EINT0_IRQn);
  312.     attach(EINT1_IRQn);
  313. //  GPIOBs.PMD.Bits.PMD14 = GPIO_PMD_INPUT;                 // GPIOB14 设置为输入方式
  314. //  GPIOBs.PMD.Bits.PMD15 = GPIO_PMD_INPUT;                 // GPIOB15 设置为输入方式
  315. //  SYSs.GPBMFP.Regs |= (1 << GCR_GPBMFP_INT1_SS31)         // 复用 INT1
  316. //                      | (1 << GCR_GPBMFP_INT0);           // 复用 INT0
  317. //  GPIOBs.DBEN.Regs = (1 << Pin15) | (1 << Pin14);         // 开启防抖
  318.     GPIOBs.IEN.Regs = (1 << Pin15) | (1 << Pin14);          // 开启中断
  319.     vector_t::enable(EINT0_IRQn);
  320.     vector_t::enable(EINT1_IRQn);
  321. }
  322. // eint 中断服务例程
  323. bool eint_t::isr(int vector)
  324. {
  325.     GPIOBs.ISRC.Regs = GPIOBs.ISRC.Regs;            // 清中断 flag
  326.     return true;
  327. }
  328. // eint 中断滞后服务例程
  329. void eint_t::dsr(int vector, uintptr_t count)
  330. {
  331.     mbox.do_tryput(vector == EINT0_IRQn ? 2 : 1);       // 发送消息
  332. }
  333. eint_t eint;                                    // 创建 eint 对象
目标文件名.h中,需要在
  1.     void routine();          // 任务例程
之后,插入下面的代码:
  1. private:
  2.     uint8_t buffer[12];        // 1-wire 输入数据缓冲
  3.     char str[28];                 // uart0 输出数据缓冲
init_config.h 的 Configuration Wizard配置:
时钟配置 \ 外设时钟配置 \ UART_S: 选择“外部 4~24Mhz 晶振时钟”
时钟配置 \ 外设时钟配置 \ UART0_EN: YES
时钟配置 \ 外设时钟配置 \ UART1_EN: YES
GPIOB 管脚配置 \ GPB_MFP, ALT_MFP: 多功能管脚选择 \ PB.0: 选择 “RXD0”
GPIOB 管脚配置 \ GPB_MFP, ALT_MFP: 多功能管脚选择 \ PB.1: 选择 “TXD0”
GPIOB 管脚配置 \ GPB_MFP, ALT_MFP: 多功能管脚选择 \ PB.4: 选择 “RXD1”
GPIOB 管脚配置 \ GPB_MFP, ALT_MFP: 多功能管脚选择 \ PB.5: 选择 “TXD1”
GPIOB 管脚配置 \ GPB_MFP, ALT_MFP: 多功能管脚选择 \ PB.14: 选择 “INT0”
GPIOB 管脚配置 \ GPB_MFP, ALT_MFP: 多功能管脚选择 \ PB.15: 选择 “INT1”
GPIOB 管脚配置 \ GPIOB_PMD: 端口模式 \ PB.10: 选择 “输出”
GPIOB 管脚配置 \ GPIOB_PMD: 端口模式 \ PB.14: 选择 “输入”
GPIOB 管脚配置 \ GPIOB_PMD: 端口模式 \ PB.15: 选择 “输入”
GPIOB 管脚配置 \ GPIOB_DOUT: 输出值 \ PB.10: 选择 “低”
GPIOB 管脚配置 \ GPIOB_DBEN: 去抖使能 \ PB.14: YES
GPIOB 管脚配置 \ GPIOB_DBEN: 去抖使能 \ PB.15: YES
中断去抖配置 \ DBCLKSEL 去抖采样周期选择:选择 “每 128 去抖时钟采样中断输入一次”
中断去抖配置 \ DBCLKSRC 去抖计数器时钟源选择:选择 “内部 10KHz 时钟”

应大家要求,上传工程:

本帖子中包含更多资源

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

×
dong_abc 发表于 2011-4-23 13:17 | 显示全部楼层
程序框架做得真好~~~
您需要登录后才可以回帖 登录 | 注册

本版积分规则

33

主题

1466

帖子

21

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

33

主题

1466

帖子

21

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