[LOOK] LOOK+红杏头文件 学习第六帖:I2C(中断方式)

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

-----------------2011-06-14---------------
在原基础上做如下调整:
① 增加main.h文件 包含所需头文件
② 继承于interrupt_t的中断抽象类I2C1_t:I2C接口的单字节及多字节的读写操作;
③ task_AT24C16_t:接收UART命令完成对AT24C16的单字节及多字节的读写操作;
   'r'为读地址0x00单字节指令、'u'为地址0x00单字节加1并存储指令、d'为地址0x00单字节减1并存储指令;
   R'为读地址0x10开始单页指令、'u'为地址0x10开始单页加1并存储指令、'D'为地址0x10开始单页减1并存储指令。


初始化设置:HCLK时钟源:外部 4~24MHz 晶振使能
                分频: 1
               I2C1时钟使能
               PA.10 PA.11配置为I2C功能


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

初始化设置: PB.0选择多功能输入RXD0 PB.1选择多功能输入TXD0
            UART时钟选择外部12MHZ,并使能UART0时钟
--------------------------------------------------2011-06-12 PM--------------------------------------------------
在原基础上做如下调整:
① 增加任务类task_ad_t,完成对AD1的单次AD转换并通过串口发送转换结果;
② 使用信号灯作为在UART0接收字符'3'时AD转换任务的同步。

初始化设置:ADC时钟选择外部12MHz,分频为3 并使能ADC时钟
            PA.1配置为AD引脚功能


源程序:
main.h
  1. #ifndef __LOOK_MAIN_H
  2. #define __LOOK_MAIN_H

  3. /*------------------------------------
  4. LOOK头文件放入此处
  5. ------------------------------------*/
  6. #include "look_config.h"
  7. #include <look.h>
  8. #include <instantiate>

  9. /*------------------------------------
  10. 芯片及红杏头文件放入此处
  11. ------------------------------------*/
  12. #include "NUC1xx.h"
  13. #include "NUC1xxM051Seriescfg.h"

  14. /*------------------------------------
  15. 系统定义的C++语言的头文件应该放入此处
  16. ------------------------------------*/
  17. #include "led.h"
  18. #include "I2C.h"

  19. /*------------------------------------
  20. 全局类对象实例声明放入此位置
  21. ------------------------------------*/
  22. #endif
led.h
  1. #ifndef __LOOK_LED_H
  2. #define __LOOK_LED_H

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

  4. // 任务类 task_led_t 的定义
  5. class task_led_t : public task_t {
  6. public:
  7. task_led_t() __OPT_ATTR__; // 构造函数
  8. protected:
  9. void routine(); // 任务例程
  10. };
  11. // 任务类 task_led_t 的构造函数
  12. __OPT_INLINE__ task_led_t::task_led_t()
  13. {
  14. // TODO: 在此初始化 task_led_t 的类成员
  15. }


  16. // 任务类 task_key_t 的定义
  17. class task_key_t : public task_t {
  18. public:
  19. task_key_t() __OPT_ATTR__; // 构造函数
  20. int32_t key_read() __OPT_ATTR__;
  21. protected:
  22. void routine(); // 任务例程
  23. };
  24. // 任务类 task_key_t 的构造函数
  25. __OPT_INLINE__ task_key_t::task_key_t()
  26. {
  27. // TODO: 在此初始化 task_key_t 的类成员
  28. }


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


  41. // 任务类 task_ad_t 的定义
  42. class task_ad_t : public task_t {
  43. public:
  44. task_ad_t() __OPT_ATTR__; // 构造函数
  45. sem_t sem; // 信号灯为AD转换提供同步
  46. protected:
  47. void routine(); // 任务例程
  48. };
  49. // 任务类 task_beep_t 的构造函数
  50. __OPT_INLINE__ task_ad_t::task_ad_t():sem(0)
  51. {
  52. // TODO: 在此初始化 task_ad_t 的类成员
  53. }

  54. // uart0_t 类为应用层提供了简单的 uart 同步输出功能及接收功能。
  55. class uart0_t : public interrupt_t {
  56. public:
  57. uart0_t() __OPT_ATTR__; //构造函数
  58. void puts(const char* str); //串口输出函数
  59. void put_numeral(uint8_t data);
  60. protected:
  61. bool isr(int vector); //中断服务例程
  62. void dsr(int vector, uintptr_t count); //中断滞后服务例程
  63. private:
  64. void fillfifo(const char* str); //填充FIFO
  65. private:
  66. const char* buffer; // 输出缓冲区
  67. task_t* task; // 正在输出的任务
  68. };
  69. extern uart0_t uart0; // 创建 uart0 对象

  70. // 任务类 task_AT24C16_t 的定义
  71. class task_AT24C16_t : public task_t {
  72. public:
  73. task_AT24C16_t() __OPT_ATTR__; // 构造函数
  74. protected:
  75. void routine(); // 任务例程
  76. };
  77. // 任务类 task_beep_t 的构造函数
  78. __OPT_INLINE__ task_AT24C16_t::task_AT24C16_t()
  79. {
  80. // TODO: 在此初始化 task_ad_t 的类成员
  81. }


  82. extern instantiate::task<task_led_t, LOOK_STACK_SIZE> task_led;
  83. extern instantiate::task<task_key_t, LOOK_STACK_SIZE> task_key;
  84. extern instantiate::task<task_beep_t, LOOK_STACK_SIZE> task_beep;
  85. extern instantiate::task<task_ad_t, LOOK_STACK_SIZE> task_ad;
  86. extern instantiate::task<task_AT24C16_t, LOOK_STACK_SIZE> task_AT24C16;

  87. #endif
I2C.h

  1. #ifndef __LOOK_I2C_H
  2. #define __LOOK_I2C_H
  3. // I2C1_t 类为应用层提供了 I2C 接口
  4. class I2C1_t : public interrupt_t {
  5. public:
  6.     I2C1_t() __OPT_ATTR__;   //构造函数
  7.     sem_t sem;      // 信号灯为AD转换提供同步
  8. protected:
  9. bool isr(int vector);   //中断服务例程
  10. void dsr(int vector, uintptr_t count); //中断滞后服务例程
  11. private://私有方法
  12.     inline void Start(void);//复位I2C
  13.     inline void REStart(void);//重复位I2C
  14. //inline void Wait(void);//超时等待
  15. inline void Exit(void);//出错退出
  16.     inline void Stop(void);//成功结束
  17. public://公有方法及属性
  18. unsigned char ReadByte(unsigned int Address, unsigned char *Data);//读字节函数(方法)
  19. unsigned char WriteByte(unsigned int, unsigned char);//写字节函数(方法)
  20. unsigned char ReadBuffer(unsigned int, unsigned char *, unsigned int);//读块函数(方法)
  21. unsigned char WriteBuffer(unsigned int, unsigned char *, unsigned int);//写块函数(方法)
  22. void SetAddress(unsigned int I2CAddress);//公有只写方法(属性)
  23. //void WriteWait(void);//EEPROM写入等待函数(方法)
  24. unsigned int GetState(void);//公有只读方法(属性)
  25. //void SetSystickCount(void);//公有只写方法(属性)
  26. private://私有属性
  27. volatile bool Busy;//忙属性
  28. volatile unsigned int State;//私有属性
  29. //volatile unsigned int SystickCount;//私有属性
  30. volatile unsigned int Count;//私有属性
  31. volatile unsigned int MainCount, SubCount;//主从计数
  32. volatile unsigned int SubAddr;//私有属性
  33. volatile unsigned char MainComm, SubComm;//主从通讯命令
  34. volatile unsigned char TxBuffer[16], RxBuffer[16];//接收数据缓冲区
  35. };
  36. extern I2C1_t I2C_1;
  37. #endif
工程结构截图:


工程包:

本帖子中包含更多资源

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

×
 楼主| Swallow_0322 发表于 2011-6-14 17:16 | 显示全部楼层
本帖最后由 Swallow_0322 于 2011-6-14 17:38 编辑

源文件:
I2C.CPP

  1. #include "main.h"

  2. __OPT_INLINE__ I2C1_t::I2C1_t():sem(0) //构造函数
  3. {
  4. //I2C的引脚配置及时钟配置使用LOOK配置

  5. SubAddr = 0xA0; //I2C设备地址
  6. for (uint32_t i = 0; i < sizeof(TxBuffer); i ++)
  7. { //清空缓存
  8. TxBuffer = 0;
  9. RxBuffer = 0;
  10. }
  11. SYSCLKs.APBCLK.Bits.I2C1_EN = 1;
  12. SYSs.IPRSTC2.Bits.I2C1_RST = 1; //I2C1模块复位
  13. SYSs.IPRSTC2.Bits.I2C1_RST = 0; //I2C1正常工作
  14. I2C1s.CON.Bits.ENSI = 1; //允许I2C串行功能
  15. I2C1s.CLK.Regs = ((12000000/2*10)/(50000 * 4) + 5) / 10 - 1;
  16. I2C1s.CON.Bits.EI = 1; //I2C1 使能中断
  17. I2C1s.CON.Bits.STA = 0; //I2C1起始标志清零
  18. I2C1s.CON.Bits.STO = 0; //I2C1结束标志清零
  19. I2C1s.CON.Bits.AA = 0; //I2C1应答标志清零
  20. I2C1s.CON.Bits.EI = 1; //I2C1 使能中断
  21. I2C1s.CON.Bits.ENSI = 1; //允许I2C串行功能
  22. I2C1s.CON.Bits.SI= 1; //清中断标志位

  23. attach(I2C1_IRQn);
  24. vector_t::enable(I2C1_IRQn);
  25. }

  26. // 中断服务例程
  27. bool I2C1_t::isr(int vector)
  28. {
  29. bool Back_Val = FALSE;
  30. switch(I2C1s.STATUS.Regs& 0xf8)
  31. {
  32. case I2C_START: //主机收到自己发送的开始信号
  33. if (State == I2C_START) { //本次中断应该接收TW_START信号
  34. I2C1s.DATA.Regs = SubAddr & 0xfe; //发送子机地址(写)
  35. I2C1s.CON.Bits.STA = 0;
  36. I2C1s.CON.Bits.SI = 1; //STA位必须清除,否则死机 清除中断标志
  37. State = I2C_MT_SLA_ACK; //Status下次I2C_MT_SLA_ACK
  38. }
  39. else
  40. {
  41. Exit(); //通讯失败
  42. Back_Val = TRUE;
  43. }
  44. break;
  45. case I2C_REP_START: //主机收到自己发送的重新开始信号
  46. if (State == I2C_REP_START) { //本次中断应该接收TW_RESTART信号
  47. I2C1s.DATA.Regs = SubAddr | 0x01; //发送子机地址(读)
  48. I2C1s.CON.Bits.STA = 0; //STA位必须清除,否则死机 清除中断标志
  49. I2C1s.CON.Bits.SI = 1;
  50. I2C1s.CON.Bits.AA = 1;
  51. State = I2C_MR_SLA_ACK; //Status下次I2C_MR_SLA_ACK
  52. }
  53. else
  54. {
  55. Exit(); //通讯失败
  56. Back_Val = TRUE;
  57. }
  58. break;
  59. case I2C_MT_SLA_ACK: //主发机接收到从机的地址应答信号后发送命令
  60. if (State == I2C_MT_SLA_ACK) { //本次中断应该接收TW_MT_SLA_ACK信号
  61. State = I2C_MT_DATA_ACK; //Status下次应该收TW_MT_DATA_ACK
  62. I2C1s.DATA.Regs = SubComm; //发送子机命令
  63. I2C1s.CON.Bits.SI = 1;
  64. I2C1s.CON.Bits.AA = 1;
  65. }
  66. else
  67. {
  68. Exit(); //通讯失败
  69. Back_Val = TRUE;
  70. }
  71. break;
  72. case I2C_MR_SLA_ACK: //主收机接收到从机的地址应答信号
  73. if ((State == I2C_MR_SLA_ACK) && SubCount) { //本次中断应该接收TW_MR_SLA_ACK信号
  74. State = I2C_MR_DATA_ACK; //Status下次应该收TW_MR_DATA_ACK
  75. I2C1s.CON.Bits.SI = 1;
  76. I2C1s.CON.Bits.AA = 1;
  77. }
  78. else
  79. {
  80. Exit(); //通讯失败
  81. Back_Val = TRUE;
  82. }
  83. break;
  84. case I2C_MT_DATA_ACK: //主收机接收到从机的数据应答信号
  85. if ((State == I2C_MT_DATA_ACK) && (Count < MainCount)) {//本次中断应该接收TW_MT_DATA_ACK信号
  86. I2C1s.DATA.Regs = TxBuffer[Count ++];//发送子机数据
  87. I2C1s.CON.Bits.SI = 1;
  88. I2C1s.CON.Bits.AA = 1;
  89. }
  90. else {
  91. if ((State == I2C_MT_DATA_ACK) && (Count == MainCount) && (SubAddr & 1)) {//本次中断应该接收TW_MT_DATA_ACK信号
  92. REStart();//
  93. }
  94. else
  95. {
  96. Stop(); //通讯成功
  97. Back_Val = TRUE;
  98. }
  99. }
  100. break;
  101. case I2C_MR_DATA_ACK:
  102. if ((State == I2C_MR_DATA_ACK) && (Count < SubCount)) {
  103. RxBuffer[Count ++] = I2C1s.DATA.Regs;//接收子机数据
  104. if (Count < SubCount) {
  105. I2C1s.CON.Bits.SI = 1;
  106. I2C1s.CON.Bits.AA = 1;
  107. }
  108. else {
  109. I2C1s.CON.Bits.AA = 0;
  110. I2C1s.CON.Bits.SI = 1;
  111. State = I2C_MR_DATA_NACK;//下次进入I2C_MR_DATA_NACK,接收数据准备完成
  112. }
  113. }
  114. else
  115. {
  116. Exit(); //通讯失败
  117. Back_Val = TRUE;
  118. }
  119. break;
  120. case I2C_MR_DATA_NACK: //数据接收结束
  121. if ((State == I2C_MR_DATA_NACK) && (Count == SubCount)) {
  122. Stop(); //通讯成功
  123. }
  124. else Exit(); //通讯失败
  125. Back_Val = TRUE;
  126. break;
  127. // case I2C_MT_DATA_NACK:
  128. // Exit();//通讯失败
  129. // break;
  130. default:
  131. Exit(); //通讯失败
  132. Back_Val = TRUE;
  133. break;
  134. }
  135. return Back_Val;
  136. }

  137. // 中断滞后服务例程
  138. void I2C1_t::dsr(int vector, uintptr_t count)
  139. {
  140. sem.do_post(); //释放一个信号量资源
  141. }


  142. void I2C1_t::Start(void)
  143. {
  144. Busy = true;
  145. State = I2C_START; //主机准备发送启始位
  146. Count = 0; //发送数据个数
  147. //SystickCount = 0; //清除节拍计数器
  148. I2C1s.CON.Bits.STO = 0; //I2C1结束标志清零
  149. I2C1s.CON.Bits.AA = 0; //I2C1应答标志清零
  150. I2C1s.CON.Bits.EI = 1; //I2C1 使能中断
  151. I2C1s.CON.Bits.ENSI = 1; //允许I2C串行功能
  152. I2C1s.CON.Bits.SI= 1; //清中断标志位
  153. I2C1s.CON.Bits.STA = 1; //I2C1起始标志置位
  154. //delay(LOOK_TICKS_PER_SEC);
  155. while(!sem.wait());
  156. // task = &scheduler.get_current_task();
  157. // delay(); // 阻塞任务
  158. }

  159. void I2C1_t::REStart(void)
  160. {
  161. Busy = true;
  162. State = I2C_REP_START; //主机准备发送启始位
  163. Count = 0; //发送数据个数
  164. I2C1s.CON.Bits.STA = 1; //I2C1起始标志置位
  165. I2C1s.CON.Bits.SI= 1; //清中断标志位*/
  166. }

  167. void I2C1_t::Stop(void)
  168. {
  169. Busy = false;
  170. State = I2C_BUS_OK;//通讯成功
  171. I2C1s.CON.Bits.STO = 1; //I2C1结束标志置位
  172. I2C1s.CON.Bits.SI = 1; //清中断标志位*/
  173. }

  174. void I2C1_t::Exit(void)
  175. {
  176. Busy = false;
  177. State = I2C_BUS_ERROR; //通讯失败
  178. I2C1s.CON.Bits.STO = 1; //I2C1结束标志置位
  179. I2C1s.CON.Bits.SI = 1; //清中断标志位
  180. }

  181. unsigned char I2C1_t::ReadByte(unsigned int Address, unsigned char *Data)
  182. {
  183. SubAddr |= 0x01;
  184. MainCount = 0; //发送0个数据(只读)
  185. //本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
  186. SubComm = Address; //读出地址
  187. SubCount = 1; //接收1个数据
  188. //SystickCount = 0;
  189. Start(); //启动I2C模块
  190. if (State == I2C_BUS_OK)
  191. {
  192. //通讯成功
  193. Data[0] = RxBuffer[0]; //从接收缓冲区取出一个字节
  194. }
  195. return State; //(读出数据在RxBuffer[0]~RxBuffer[15])
  196. }

  197. unsigned char I2C1_t::WriteByte(unsigned int Address, unsigned char Data)
  198. {
  199. SubAddr &= 0xfe;
  200. MainCount = 1; //发送1个数据
  201. //本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
  202. SubComm = Address; //写入地址
  203. TxBuffer[0] = Data; //写入1个数据到发送缓冲区
  204. SubCount = 0; //接收0个数据
  205. Start(); //启动I2C模块
  206. delay(LOOK_TICKS_PER_SEC/10); //延时100mS等待写入完成
  207. return State;
  208. }

  209. unsigned char I2C1_t::ReadBuffer(unsigned int Address, unsigned char *Data, unsigned int Cnt)
  210. {
  211. SubAddr |= 0x01;
  212. MainCount = 0;//发送0个数据(只读)
  213. //本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
  214. SubComm = Address;//读出地址
  215. SubCount = (Cnt <= sizeof(RxBuffer)) ? Cnt : sizeof(RxBuffer);//接收Cnt个数据
  216. Start();//启动I2C模块
  217. if (State == I2C_BUS_OK) {//通讯成功
  218. for (uint8_t i = 0; i < SubCount; i ++) Data = RxBuffer;//从接收缓冲区取出Cnt个字节
  219. }
  220. return State;//(读出数据在RxBuffer[0]~RxBuffer[15])
  221. }

  222. unsigned char I2C1_t::WriteBuffer(unsigned int Address, unsigned char *Data, unsigned int Cnt)
  223. {
  224. SubAddr &= 0xfe;
  225. MainCount = (Cnt <= sizeof(TxBuffer)) ? Cnt : sizeof(TxBuffer);//发送Cnt个数据
  226. //本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
  227. SubComm = Address;//写入地址
  228. for (uint8_t i = 0; i < MainCount; i ++) TxBuffer = Data;//写入Cnt个数据到发送缓冲区
  229. SubCount = 0;//接收0个数据
  230. Start();//启动I2C模块
  231. delay(LOOK_TICKS_PER_SEC/10); //延时100mS等待写入完成
  232. return State;
  233. }


  234. unsigned int I2C1_t::GetState(void)
  235. {
  236. return State;
  237. }

  238. void I2C1_t::SetAddress(unsigned int I2CAddress)
  239. {
  240. SubAddr = I2CAddress;
  241. }

  242. /*void I2cObj::SetSystickCount(void)
  243. {
  244. SystickCount ++;
  245. }*/

  246. I2C1_t I2C_1;


led.cpp

  1. #include "main.h"
  2. flag_t Flag(0);  //位0为LED闪烁模式  位1为KEY1控制蜂鸣器任务同步标志   位2为UART通信控制蜂鸣器任务同步标志
  3. flag_t Flag_I2C(0);  //通过I2C读写AT24c16同步标志
  4. // uart0 构造函数
  5. __OPT_INLINE__ uart0_t::uart0_t()
  6. {
  7.     attach(UART0_IRQn);
  8.     vector_t::enable(UART0_IRQn);
  9.     SYSs.IPRSTC2.Bits.UART0_RST = 1;  //UART0 模块复位
  10.     SYSs.IPRSTC2.Bits.UART0_RST = 0;  //UART0 模块正常工作
  11.     UART0s.FCR.Bits.TFR = 1;    //TX 软件复位
  12.     UART0s.FCR.Bits.RFR = 1;    //RX 软件复位
  13.     UART0s.FCR.Bits.RFITL = 0x00;   //Rx FIFO中断 (INT_RDA) 触发级别   1位
  14.    
  15. UART0s.LCR.Bits.SPE = 0;    //无校验  奇偶使能位
  16. UART0s.LCR.Bits.EPE = 0;                //  0----奇校验 1----偶校验
  17. UART0s.LCR.Bits.PBE = 0;   
  18.     UART0s.LCR.Bits.WLS = 0b011;   //字长度选择 8bits
  19.     UART0s.LCR.Bits.NSB = 0;    //1位停止位
  20.    
  21. UART0s.BAUD.Bits.BRD = 0x66;   //外部12MHz 115200bps  对波特率分频寄存器的设置波特率分频设置即该句必须放在第一位
  22. UART0s.BAUD.Bits.DIV_X_EN = 1;   //使能分频X
  23. UART0s.BAUD.Bits.DIV_X_ONE = 1;   //Divider X equal 1
  24. UART0s.IER.Bits.RDA_IEN = 1;   //使能接收中断
  25.     /*
  26.      DIV_X_EN  DIV_X_ONE  Divider X  BRD  波特率公式
  27. Disable       0         B        A   UART_CLK / [16 * (A+2)]
  28. Enable        0         B        A   UART_CLK / [(B+1) * (A+2)] , B must >= 8
  29. Enable        1         B        A   UART_CLK / (A+2), A must >=3
  30. */
  31. }
  32. // uart0 输出
  33. void uart0_t::puts(const char* str)
  34. {
  35.     fillfifo(str);                  // 填充 fifo
  36.     UART0s.IER.Bits.THRE_IEN = 1;   // 允许发送中断
  37.     task = &scheduler.get_current_task();
  38.     delay();                        // 阻塞任务
  39. }
  40. void uart0_t::put_numeral(uint8_t data)
  41. {
  42. char str[2];
  43. char *p;
  44. str[0] = ((data/16%16>9)?(data/16%16+'A'-10)data/16%16+'0'));
  45. str[1] = ((data%16>9)?(data%16+'A'-10)data%16+'0'));
  46. p = &str[0];
  47. puts(p);
  48. }
  49. // uart0 中断服务例程
  50. bool uart0_t::isr(int vector)
  51. {
  52. if (UART0s.ISR.Bits.THRE_INT==1)
  53. {
  54.   //UART0发送中断
  55.      const char* str = buffer;
  56.      if (str == 0) {                     // 无数据
  57.          UART0s.IER.Bits.THRE_IEN = 0;   // 禁止发送中断
  58.          return true;
  59.      }
  60.      fillfifo(str);                      // 填充 fifo
  61.      return false;
  62. }
  63. if (UART0s.ISR.Bits.RDA_INT==1)
  64. {
  65.   //UART0接收中断
  66.   /* Get all the input characters */
  67.   while(UART0s.ISR.Bits.RDA_IF)
  68.   {
  69.    /* Get the character from UART Buffer */
  70.    char Received_Data = UART0s.DATA.Regs;
  71.    switch (Received_Data)
  72.    {
  73.     case '1':
  74.      //执行蜂鸣器响3次的任务
  75.      Flag.do_set_bits(0b0100);
  76.      break;
  77.     case '3':
  78.      task_ad.sem.do_post();   //释放一个信号量资源
  79.      break;
  80.     case 'R':
  81.      Flag_I2C.do_set_bits(0b01);
  82.      break;
  83.     case 'r':
  84.      Flag_I2C.do_set_bits(0b010);
  85.      break;
  86.     case 'U':
  87.      Flag_I2C.do_set_bits(0b0100);
  88.      break;
  89.     case 'u':
  90.      Flag_I2C.do_set_bits(0b01000);
  91.      break;
  92.     case 'D':
  93.      Flag_I2C.do_set_bits(0b010000);
  94.      break;
  95.     case 'd':
  96.      Flag_I2C.do_set_bits(0b0100000);
  97.      break;
  98.     case '2':
  99.      //执行与KEY2相同的动作
  100.      int ** = Flag.peek();
  101.        if (**&0b01)
  102.          Flag.do_mask_bits(~0b01);  //清除事件标志 位0
  103.         else
  104.          Flag.do_set_bits(0b01);  //置位事件标志 位0
  105.         break;
  106.    }
  107.    return false;
  108.   }
  109. }
  110. return false;
  111. }
  112. // uart0 中断滞后服务例程
  113. // 所有数据发送完成后,dsr() 被调用
  114. void uart0_t::dsr(int vector, uintptr_t count)
  115. {
  116.     task->do_wakeup();              // 唤醒任务
  117. }
  118. // uart0 填充 fifo
  119. void uart0_t::fillfifo(const char* str)
  120. {
  121.     do {
  122.         char ch;
  123.         ch = *str++;
  124.         if (ch == 0) {
  125.             str = 0;
  126.             break;
  127.         }
  128.         UART0s.DATA.Regs = ch;
  129.     } while (!UART0s.FSR.Bits.TX_FULL);
  130.     buffer = str;
  131. }
  132. uart0_t uart0;              // 创建 uart0 对象
  133. // 任务类 task_led_t 的例程
  134. void task_led_t::routine()
  135. {
  136. // TODO: 在此编写 task_led_t 例程的内容
  137. GPIOAs.DMASK.Regs = ~0b111100;
  138. GPIOAs.DOUT.Regs = ~0b100;
  139. while (true)
  140. {
  141.    // TODO: 在此编写 task_led_t 例程的内容
  142.     uint32_t data = GPIOAs.DOUT.Regs & 0b111100;
  143.     int flag = Flag.peek();
  144.     if (flag)
  145.     {
  146.       data <<= 1;
  147.       data += data >> 4;
  148.     }
  149.     else
  150.     {
  151.       data >>= 1;
  152.       data += data << 4;
  153.     }
  154.     GPIOAs.DOUT.Regs = data;
  155.     delay(LOOK_TICKS_PER_SEC/2);
  156. }
  157. }
  158. // 任务类 task_key_t 的例程
  159. void task_key_t::routine()
  160. {
  161. // TODO: 在此编写 task_key_t 例程的内容
  162. while (true)
  163. {
  164.     // TODO: 在此编写 task_key_t 例程的内容
  165.     uint32_t Key_Val = key_read();
  166.   if ((Key_Val&(1<<14))==0)
  167.   {
  168.    //KEY2 按下
  169.    int ** = Flag.peek();
  170.      if (**&0b01)
  171.        Flag.mask_bits(~0b01);  //清除事件标志 位0
  172.       else
  173.        Flag.set_bits(0b01);  //置位事件标志 位0
  174.   }
  175.   if ((Key_Val&(1<<15))==0)
  176.   {
  177.    //KEY1 按下
  178.    Flag.do_set_bits(0b010);
  179.   }
  180.     delay(LOOK_TICKS_PER_SEC/10);
  181. }
  182. }
  183. // 任务类 task_key_t 的成员函数
  184. __OPT_INLINE__ int32_t task_key_t::key_read()
  185. {
  186. uint32_t Key_Tmp = TRUE;
  187. static uint32_t Key_Record = KEY_NO_DOWN;   //按键记录
  188. Key_Tmp = GPIOBs.PIN.Regs&KEY_NO_DOWN;
  189. if(Key_Tmp==KEY_NO_DOWN)          //无有效按键按下
  190. {
  191.    Key_Record = KEY_NO_DOWN;     //清除按键记录
  192.     return KEY_NO_DOWN;          //程序退出
  193. }
  194. if(Key_Record!=Key_Tmp)         //为新按键
  195. {
  196.     Key_Record = Key_Tmp;        //保存本次结果
  197.     delay(LOOK_TICKS_PER_SEC/100);    //延时去抖动
  198.     Key_Tmp = GPIOBs.PIN.Regs&KEY_NO_DOWN;
  199.     if(Key_Tmp==Key_Record)
  200.     return Key_Tmp;
  201. }
  202. return KEY_NO_DOWN;
  203. }
  204. // 任务类 task_beep_t 的例程
  205. void task_beep_t::routine()
  206. {
  207. // TODO: 在此编写 task_beep_t 例程的内容
  208.     GPIOBs.DOUT.Bits.Pin10 = 0;     //蜂鸣器不响
  209. while (true)
  210. {
  211.     // TODO: 在此编写 task_beep_t 例程的内容
  212.     int flag = Flag.wait(0b110, flag_t::ANY_CONSUME);  
  213.      if (flag)
  214.      {
  215.       uart0.puts("Buzzer rang three times!\n");
  216.         for (uint32_t i = 0; i < 6; i ++)
  217.       {  
  218.     //蜂鸣器响三次
  219.           GPIOBs.DOUT.Bits.Pin10 ^= 1;   //蜂鸣器响PB10=1,不响PB10=0
  220.               delay(LOOK_TICKS_PER_SEC);   //断续间隔
  221.       }
  222.       }
  223. }
  224. }   
  225. // 任务类 task_ad_t 的例程
  226. void task_ad_t::routine()
  227. {
  228. // TODO: 在此编写 task_ad_t 例程的内容
  229. SYSs.IPRSTC2.Bits.ADC_RST = 1;
  230. SYSs.IPRSTC2.Bits.ADC_RST = 0;  /* Reset ADC */
  231. //ADC时钟、分频及配置为AD引脚在look中配置
  232. ADCs.ADCR.Bits.ADEN = 1;   //使能AD模块
  233. ADCs.ADCALR.Bits.CALEN = 1;   //自校正使能
  234. while(!ADCs.ADCALR.Bits.CALDONE); //等待自校正结束
  235. ADCs.ADCR.Bits.DIFFEN = 0;   //单端输入
  236. ADCs.ADCR.Bits.ADST = 0;   //停止AD
  237. ADCs.ADCR.Bits.ADMD = 0;   //单一转换
  238. ADCs.ADCHER.Bits.CHEN = 0x02;  //模拟输入通道1使能
  239. ADCs.ADSR.Bits.ADF = 1;    //清AD中断标志
  240. while (true)
  241. {
  242.     // TODO: 在此编写 task_ad_t 例程的内容
  243.   if (sem.wait())
  244.   {
  245.    ADCs.ADCR.Bits.ADST = 1; //启动AD
  246.    while(!ADCs.ADSR.Bits.ADF); //等待转换结束
  247.    ADCs.ADSR.Bits.ADF = 1;  //清AD中断标志
  248.    uint32_t AD_Result = ADCs.ADDR1.Regs&0xFFF;
  249.    char str[4];
  250.    char *p;
  251.    str[0] = AD_Result/1000+'0';
  252.    str[1] = AD_Result/100%10+'0';
  253.    str[2] = AD_Result/10%10+'0';
  254.    str[3] = AD_Result%10+'0';
  255.    p = &str[0];
  256.    uart0.puts("ADC_RESULT_AD1:");
  257.    uart0.puts(p);
  258.   }
  259.   
  260. }
  261. }
  262. // 任务类 task_AT24C16_t 的例程
  263. void task_AT24C16_t::routine()
  264. {
  265. // TODO: 在此编写 task_beep_t 例程的内容
  266. uint8_t EEPROM_Data = 0;  //IIC地址0x00读写数据
  267. uint8_t I2C_Page_Test[16];  //IIC地址0x10页读写数据
  268. uint8_t i = 0;
  269. while (true)
  270. {
  271.     // TODO: 在此编写 task_beep_t 例程的内容
  272.     //uint8_t ** = Flag_I2C.peek();
  273.     int flag = Flag_I2C.wait(0b0111111, flag_t::ANY_CONSUME);
  274.      switch (flag)
  275.      {
  276.       case 0x01:
  277.     if (I2C_BUS_OK==I2C_1.ReadBuffer(0x10,I2C_Page_Test,16))
  278.     {
  279.      uart0.puts("\nAT24C16地址0x10开始16字节的内容为:\n");
  280.      for (i=0;i<16;i++)
  281.       uart0.put_numeral(I2C_Page_Test);
  282.     }
  283.     else
  284.      uart0.puts("\nAT24C16地址0x10开始16字节的内容读取失败!");
  285.     break;
  286.    case 0x02:
  287.     if (I2C_BUS_OK==I2C_1.ReadByte(0x00,&EEPROM_Data))
  288.     {
  289.      uart0.puts("\nAT24C16地址0的内容为:0x");
  290.      uart0.put_numeral(EEPROM_Data);
  291.     }
  292.     else
  293.      uart0.puts("\nAT24C16地址0的内容读取失败!");
  294.     break;
  295.    case 0x04:
  296.     for (i=0;i<16;i++)
  297.      I2C_Page_Test++;
  298.     if (I2C_BUS_OK==I2C_1.WriteBuffer(0x10,I2C_Page_Test,16))
  299.      uart0.puts("\nAT24C16地址0x10开始16字节的内容加1成功!");
  300.     else
  301.     {
  302.      uart0.puts("\nAT24C16地址0x10开始16字节的内容加1失败!");
  303.      for (i=0;i<16;i++)
  304.       I2C_Page_Test--;
  305.     }
  306.     break;
  307.    case 0x08:
  308.     if (I2C_BUS_OK==I2C_1.WriteByte(0x00,++EEPROM_Data))
  309.      uart0.puts("\nAT24C16地址0的内容加1成功!");
  310.     else
  311.      uart0.puts("\nAT24C16地址0的内容加1失败!");
  312.     break;
  313.    case 0x10:
  314.     for (i=0;i<16;i++)
  315.      I2C_Page_Test--;
  316.     if (I2C_BUS_OK==I2C_1.WriteBuffer(0x10,I2C_Page_Test,16))
  317.      uart0.puts("\nAT24C16地址0x10开始16字节的内容减1成功!");
  318.     else
  319.     {
  320.      uart0.puts("\nAT24C16地址0x10开始16字节的内容减1失败!");
  321.      for (i=0;i<16;i++)
  322.       I2C_Page_Test++;
  323.     }
  324.     break;
  325.    case 0x20:
  326.     if (I2C_BUS_OK==I2C_1.WriteByte(0x00,--EEPROM_Data))
  327.      uart0.puts("\nAT24C16地址0的内容减1成功!");
  328.     else
  329.      uart0.puts("\nAT24C16地址0的内容减1失败!");
  330.     break;
  331.     default:
  332.      uart0.puts("\nAT24C16读写操作错误!");
  333.         }
  334.     }
  335. }  
  336. #ifdef LOOK_SCHEDULING_PRIORITY
  337. instantiate::task<task_key_t, LOOK_STACK_SIZE> task_key(0);
  338. instantiate::task<task_beep_t, LOOK_STACK_SIZE> task_beep(3);
  339. instantiate::task<task_led_t, LOOK_STACK_SIZE> task_led(2);
  340. instantiate::task<task_ad_t, LOOK_STACK_SIZE> task_ad(1);
  341. instantiate::task<task_AT24C16_t, LOOK_STACK_SIZE> task_AT24C16(4);
  342. #else
  343. instantiate::task<task_key_t, LOOK_STACK_SIZE> task_key;
  344. instantiate::task<task_beep_t, LOOK_STACK_SIZE> task_beep;
  345. instantiate::task<task_led_t, LOOK_STACK_SIZE> task_led;
  346. instantiate::task<task_ad_t, LOOK_STACK_SIZE> task_ad;
  347. instantiate::task<task_AT24C16_t, LOOK_STACK_SIZE> task_AT24C16;
  348. #endif
hotpower 发表于 2011-6-14 19:22 | 显示全部楼层
挺好的,多任务呀,adc,uart,iic,gpio
Cube 发表于 2011-6-14 19:25 | 显示全部楼层
沙发没了。。。
 楼主| Swallow_0322 发表于 2011-6-14 19:25 | 显示全部楼层
呵呵 都是简单的应用 任务的关联不大
weshiluwei6 发表于 2011-6-14 19:26 | 显示全部楼层
太牛了太牛了太牛了 太牛了
hotpower 发表于 2011-6-14 20:40 | 显示全部楼层
水王考试完了就look
hotpower 发表于 2011-6-16 08:30 | 显示全部楼层
刚运行了三心的例程,很不错!http://bbs.21ic.com/icview-242344-1-1.html
hotpower 发表于 2011-6-16 11:51 | 显示全部楼层
运行了,很不错!
初始化蜂鸣器输出为0就好了。
 楼主| Swallow_0322 发表于 2011-6-16 14:07 | 显示全部楼层
本帖最后由 Swallow_0322 于 2011-6-16 14:08 编辑

多谢大叔关注!
现在蜂鸣器的控制初始化就是0啊,您运行有问题吗?

  1. // 任务类 task_beep_t 的例程
  2. void task_beep_t::routine()
  3. {
  4.     // TODO: 在此编写 task_beep_t 例程的内容
  5.     GPIOBs.DOUT.Bits.Pin10 = 0;     //蜂鸣器不响
  6. while (true)
  7. {
  8.     // TODO: 在此编写 task_beep_t 例程的内容
  9.     int flag = Flag.wait(0b110, flag_t::ANY_CONSUME);  
  10.      if (flag)
  11.      {
  12.       uart0.puts("Buzzer rang three times!\n");
  13.         for (uint32_t i = 0; i < 6; i ++)
  14.       {  
  15.           //蜂鸣器响三次
  16.           GPIOBs.DOUT.Bits.Pin10 ^= 1;   //蜂鸣器响PB10=1,不响PB10=0
  17.            delay(LOOK_TICKS_PER_SEC);   //断续间隔
  18.       }
  19.       }
  20. }
  21. }  
hotpower 发表于 2011-6-16 21:22 | 显示全部楼层
void task_beep_t::routine()

{

    // TODO: 在此编写 task_beep_t 例程的内容

    GPIOBs.DOUT.Bits.Pin10 = 0;     //蜂鸣器不响



这个有点慢,也可能是我设置了断点。
在老师的配置向导里要关掉快的多。
例程必须这个任务在运行状态,故初始化应该在其构造函数里面
hotpower 发表于 2011-6-17 11:37 | 显示全部楼层
今晚我想讲讲这个例程,不知道我理解正确否。
最近问iic的问题很多,刚好用这个例程讲讲。
三心的iic做了三个了,我在群里有2个。
 楼主| Swallow_0322 发表于 2011-6-17 19:01 | 显示全部楼层
void task_beep_t::routine()

{

    // TODO: 在此编写 task_beep_t 例程的内容

    GPIOBs.DOUT.Bits.Pin10 = 0;     //蜂鸣器不响



这个有点慢,也可能是我设置了断点。
在老师的配置向导里要关掉快的多。
例 ...
hotpower 发表于 2011-6-16 21:22

哦 知道了  多谢大叔指导!
 楼主| Swallow_0322 发表于 2011-6-17 19:03 | 显示全部楼层
12# hotpower

强烈支持!
这周一直在忙,SPI的例程还需稍推迟些!
hotpower 发表于 2011-6-17 19:21 | 显示全部楼层
知道了,以后你写笔记,俺评述~~~
plc_avr 发表于 2011-6-17 19:34 | 显示全部楼层
支持三心!多出笔记..........嘿嘿。
 楼主| Swallow_0322 发表于 2011-6-18 07:31 | 显示全部楼层
15# hotpower

谢谢大叔的支持,一定努力!
 楼主| Swallow_0322 发表于 2011-6-18 07:32 | 显示全部楼层
16# plc_avr

多谢烈火支持,多多指教!
hotpower 发表于 2011-6-18 07:41 | 显示全部楼层
感觉以后要多讲讲笔记
 楼主| Swallow_0322 发表于 2011-6-18 14:04 | 显示全部楼层
19# hotpower

支持!
最好对笔记内容提出些建议,作为对作笔记者的一种奖励,呵呵!
:P
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

121

主题

1393

帖子

4

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

121

主题

1393

帖子

4

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