25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 
 

389 satır
13 KiB

  1. /***********************头文件****************************/
  2. #include "main.h"
  3. #include "sys.h"
  4. #include "delay.h"
  5. #include "led.h"
  6. #include "exti.h"
  7. #include "includes.h"
  8. #include "timer.h"
  9. /***********************指针变量****************************/
  10. OS_EVENT * sem_TaskC; //任务C信号量指针
  11. OS_EVENT * sem_Mutex; //互斥信号量
  12. OS_EVENT * q_Msg; //消息队列
  13. void * MsgGrp[256]; //消息队列存储地址,最大支持256个消息
  14. /***********************全局变量****************************/
  15. u16 *I3_Num;
  16. static u16 I3_InNum; // 存储邮箱消息
  17. u32 PB4_Num; //存储按键次数
  18. u8 flag_Exit; //执行按键函数中断标志位
  19. uint8_t taskA_Num = 0 ;//记录任务A小灯闪烁次数
  20. /**********************START 任务****************************/
  21. #define START_TASK_PRIO 3 //开始任务的优先级
  22. #define START_STK_SIZE 128 //设置任务堆栈大小
  23. OS_STK START_TASK_STK[START_STK_SIZE];//任务任务堆栈
  24. void start_task(void *pdata);//任务函数
  25. /**********************任务A*********************************/
  26. #define LEDA_TASK_PRIO 4 //设置任务优先级
  27. #define LEDA_STK_SIZE 128 //设置任务堆栈大小
  28. OS_STK LEDA_TASK_STK[LEDA_STK_SIZE]; //任务堆栈
  29. void ledA_task(void *pdata); //任务函数
  30. /**********************任务B********************************/
  31. #define LEDB_TASK_PRIO 5 //设置任务优先级
  32. #define LEDB_STK_SIZE 128 //设置任务堆栈大小
  33. OS_STK LEDB_TASK_STK[LEDB_STK_SIZE]; //任务堆栈
  34. void ledB_task(void *pdata); //任务函数
  35. /**********************任务C********************************/
  36. #define LEDC_TASK_PRIO 6 //设置任务优先级
  37. #define LEDC_STK_SIZE 128 //设置任务堆栈大小
  38. OS_STK LEDC_TASK_STK[LEDC_STK_SIZE]; //任务堆栈
  39. void ledC_task(void *pdata); //任务函数
  40. /**********************任务D********************************/
  41. #define LEDD_TASK_PRIO 9 //设置任务优先级
  42. #define LEDD_STK_SIZE 128 //设置任务堆栈大小
  43. OS_STK LEDD_TASK_STK[LEDD_STK_SIZE]; //任务堆栈
  44. void ledD_task(void *pdata); //任务函数
  45. /*********************任务E********************************/
  46. #define LEDE_TASK_PRIO 10 //设置任务优先级
  47. #define LEDE_STK_SIZE 128 //设置任务堆栈大小
  48. OS_STK LEDE_TASK_STK[LEDE_STK_SIZE]; //任务堆栈
  49. void ledE_task(void *pdata); //任务函数
  50. /*********************任务F ********************************/
  51. #define LEDF_TASK_PRIO 7 //设置任务优先级
  52. #define LEDF_STK_SIZE 128 //设置任务堆栈大小
  53. OS_STK LEDF_TASK_STK[LEDF_STK_SIZE]; //任务堆栈
  54. void ledF_task(void *pdata); //任务函数
  55. /********************按键检测任务****************************/
  56. #define KEYG_TASK_PRIO 11 //设置任务优先级
  57. #define KEYG_STK_SIZE 128 //设置任务堆栈大小
  58. OS_STK KEYG_TASK_STK[KEYG_STK_SIZE]; //任务堆栈
  59. void keyG_task(void *pdata); //任务函数
  60. /********************主函数****************************/
  61. int main(void)
  62. {
  63. HSI_SetSysClock(16, 336, 2, 7); //使用HSI配置系统时钟为168M
  64. TIM3_Int_Init(4999, 8399); //时钟初始化
  65. delay_init(168); //延时初始化
  66. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组配置
  67. LED_Init(); //LED初始化
  68. EXTIX_Init(); //外部中断初始化
  69. OSInit(); //UCOS初始化
  70. OSTaskCreate(start_task, (void*)0, (OS_STK*)&START_TASK_STK[START_STK_SIZE-1], START_TASK_PRIO); //创建开始任务
  71. OSStart(); //开始任务
  72. }
  73. /******************************************************
  74. //创建UCOS开始任务
  75. //提供外设初始化、创建信号量、创建邮箱、创建消息队列
  76. 、创建信号量集、创建任务、初始化统计任务等等
  77. ********************************************************/
  78. void start_task(void *pdata)
  79. {
  80. OS_CPU_SR cpu_sr = 0;
  81. pdata=pdata;
  82. u8 err; //错误标志码
  83. sem_TaskC = OSSemCreate(0); //创建信号量
  84. msg_TaskC = OSMboxCreate((void*) 0);//创建消息邮箱
  85. sem_Mutex = OSMutexCreate(8, &err); //创建互斥信号量 设置优先级为8
  86. q_Msg = OSQCreate(&MsgGrp[0],256); //创建消息队列
  87. OSStatInit(); //开启统计任务
  88. OS_ENTER_CRITICAL(); //进入临界区(关闭中断)
  89. OSTaskCreate(ledA_task,(void*)0,(OS_STK*)&LEDA_TASK_STK[LEDA_STK_SIZE-1],LEDA_TASK_PRIO);//创建任务A
  90. OSTaskCreate(ledB_task,(void*)0,(OS_STK*)&LEDB_TASK_STK[LEDB_STK_SIZE-1],LEDB_TASK_PRIO);//创建任务B
  91. OSTaskCreate(ledC_task,(void*)0,(OS_STK*)&LEDC_TASK_STK[LEDC_STK_SIZE-1],LEDC_TASK_PRIO);//创建任务C
  92. OSTaskCreate(ledD_task,(void*)0,(OS_STK*)&LEDD_TASK_STK[LEDD_STK_SIZE-1],LEDD_TASK_PRIO);//创建任务D
  93. OSTaskCreate(ledE_task,(void*)0,(OS_STK*)&LEDE_TASK_STK[LEDE_STK_SIZE-1],LEDE_TASK_PRIO);//创建任务E
  94. OSTaskCreate(ledF_task,(void*)0,(OS_STK*)&LEDF_TASK_STK[LEDF_STK_SIZE-1],LEDF_TASK_PRIO);//创建任务F
  95. OSTaskCreate(keyG_task,(void*)0,(OS_STK*)&KEYG_TASK_STK[KEYG_STK_SIZE-1],KEYG_TASK_PRIO);//创建任务G
  96. OSTaskSuspend(START_TASK_PRIO);//挂起开始任务
  97. OS_EXIT_CRITICAL(); //退出临界区(开中断)
  98. }
  99. /********************任务A任务函数****************************
  100. 1. 任务A小灯以1Hz的频率闪烁
  101. 2. 当任务A的小灯闪烁10次过后,任务A挂起,任务B执行
  102. *************************************************************/
  103. void ledA_task(void *pdata)
  104. {
  105. pdata=pdata;
  106. NVIC_InitTypeDef NVIC_InitStructure;
  107. while(1)
  108. {
  109. if(21 <= taskA_Num)
  110. {
  111. LED0 = 1;
  112. NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
  113. NVIC_InitStructure.NVIC_IRQChannelCmd=DISABLE;
  114. NVIC_Init(&NVIC_InitStructure);
  115. OSTaskSuspend(LEDA_TASK_PRIO);//当小灯闪烁10次后,挂起任务A
  116. }
  117. }
  118. }
  119. /********************任务B任务函数****************************
  120. 1. 任务B小灯以10Hz的频率闪烁
  121. 2. 当任务B的小灯闪烁20次过后,任务B挂起,给任务C发信号量
  122. *************************************************************/
  123. void ledB_task(void *pdata)
  124. {
  125. pdata=pdata;
  126. u8 taskB_Num = 0 ;//记录任务A小灯闪烁次数
  127. while(1)
  128. {
  129. LED1 = 0;
  130. delay_ms(50);
  131. LED1 = 1;
  132. delay_ms(50);
  133. taskB_Num++;
  134. if(20 <= taskB_Num)
  135. {
  136. OSSemPost(sem_TaskC);//给任务C发信号量
  137. OSTaskSuspend(LEDB_TASK_PRIO);//当小灯闪烁20次后,挂起任务B
  138. }
  139. }
  140. }
  141. /********************任务C任务函数****************************
  142. 1. 任务C接收到任务B的信号量时,任务C执行
  143. 2. 对于外部中断的触发次数进行计数,并通过邮箱发送给任务C
  144. 3. 中断次数小于5时,任务C小灯以1Hz频率闪烁,
  145. 中断次数大于等于5,且小于10时,任务C小灯以10Hz频率闪烁
  146. 4. 任务C把通过邮箱接收到的数据填入队列
  147. *************************************************************/
  148. void ledC_task(void *pdata)
  149. {
  150. pdata=pdata;
  151. u8 err;
  152. while (1)
  153. {
  154. OSSemPend(sem_TaskC, 0, &err); //请求信号量
  155. I3_Num = (u16* )OSMboxPend(msg_TaskC, 10, &err); //请求邮箱
  156. if (I3_Num != NULL) //如果消息邮箱没有消息,返回空指针。
  157. {
  158. I3_InNum = *I3_Num;
  159. OSQPost(q_Msg, I3_Num); //发送队列消息
  160. }
  161. if (I3_InNum < 5)
  162. {
  163. LED2 = 0;
  164. delay_ms(500);
  165. LED2 = 1;
  166. delay_ms(500);
  167. }
  168. else if (I3_InNum >= 5 && I3_InNum < 10)
  169. {
  170. LED2 = 0;
  171. delay_ms(50);
  172. LED2 = 1;
  173. delay_ms(50);
  174. }
  175. OSSemPost(sem_TaskC);
  176. }
  177. }
  178. /********************任务D任务函数****************************
  179. 1、任务D获取到互斥量时任务D小灯常亮,未获取到时任务D小灯长灭
  180. 2、当外部输入1为高电平时,任务D尝试获取互斥量,
  181. 当外部输入1为低电平时,任务D释放互斥量
  182. *************************************************************/
  183. void ledD_task(void *pdata)
  184. {
  185. pdata=pdata;
  186. u8 err;
  187. while(1)
  188. {
  189. if (KEY0 == 0) //外部输入1(PI_15)为高电平,尝试获取互斥信号量
  190. {
  191. OSMutexPend(sem_Mutex, 10, &err);
  192. if (err != 10u)
  193. {
  194. LED3 = 0;
  195. }
  196. }
  197. if (KEY0 == 1) //外部输入1为低电平,释放互斥信号量
  198. {
  199. OSMutexPost(sem_Mutex);
  200. LED3 = 1;
  201. }
  202. delay_ms(10); //任务调度
  203. }
  204. }
  205. /********************任务E任务函数****************************
  206. 1、任务E获取到互斥量时任务E小灯常亮,未获取到时任务E小灯长灭
  207. 2、当外部输入2为高电平时,任务E尝试获取互斥量,
  208. 当外部输入2为低电平时,任务E释放互斥量
  209. *************************************************************/
  210. void ledE_task(void *pdata)
  211. {
  212. pdata=pdata;
  213. u8 err;
  214. while(1)
  215. {
  216. if (KEY1 == 0) //外部输入2为高电平,尝试获取互斥信号量
  217. {
  218. OSMutexPend(sem_Mutex, 10, &err);
  219. if (err != 10u)
  220. {
  221. LED4 = 0;
  222. }
  223. }
  224. if (KEY1 == 1) //外部输入2为低电平,释放互斥信号量
  225. {
  226. OSMutexPost(sem_Mutex);
  227. LED4 = 1;
  228. }
  229. delay_ms(10);
  230. }
  231. }
  232. /********************任务F任务函数****************************
  233. 1、任务E获取到互斥量时任务E小灯常亮,未获取到时任务E小灯长灭
  234. 2、当外部输入2为高电平时,任务E尝试获取互斥量,
  235. 当外部输入2为低电平时,任务E释放互斥量
  236. *************************************************************/
  237. void ledF_task(void *pdata)
  238. {
  239. pdata=pdata;
  240. u8 err;
  241. u8 num;
  242. u8 *p;
  243. while(1)
  244. {
  245. p = OSQPend(q_Msg, 0, &err); //请求消息队列
  246. if (p != NULL)
  247. {
  248. num = *p % 8;
  249. }
  250. switch (num)
  251. {
  252. case 0:
  253. LED5 = 1; LED6 = 1; LED7 = 1; LED8 = 1; LED9 = 1; LED10 = 1; LED11 = 1;
  254. LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
  255. break;
  256. case 1:
  257. LED5 = 0; LED6 = 1; LED7 = 1; LED8 = 1; LED9 = 1; LED10 = 1; LED11 = 1;
  258. LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
  259. break;
  260. case 2:
  261. LED5 = 0; LED6 = 0; LED7 = 1; LED8 = 1; LED9 = 1; LED10 = 1; LED11 = 1;
  262. LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
  263. break;
  264. case 3:
  265. LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 1; LED9 = 1; LED10 = 1; LED11 = 1;
  266. LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
  267. break;
  268. case 4:
  269. LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 1; LED10 = 1; LED11 = 1;
  270. LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
  271. break;
  272. case 5:
  273. LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 1; LED11 = 1;
  274. LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
  275. break;
  276. case 6:
  277. LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 0; LED11 = 1;
  278. LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
  279. break;
  280. case 7:
  281. LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 0; LED11 = 0;
  282. LED12 = 1; LED13 = 1; LED14 = 1; LED15 = 1;
  283. break;
  284. case 8:
  285. LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 0; LED11 = 0;
  286. LED12 = 0; LED13 = 1; LED14 = 1; LED15 = 1;
  287. break;
  288. case 9:
  289. LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 0; LED11 = 0;
  290. LED12 = 0; LED13 = 0; LED14 = 1; LED15 = 1;
  291. break;
  292. case 10:
  293. LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 0; LED11 = 0;
  294. LED12 = 0; LED13 = 0; LED14 = 0; LED15 = 1;
  295. break;
  296. case 11:
  297. LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 0; LED11 = 0;
  298. LED12 = 0; LED13 = 0; LED14 = 0; LED15 = 0;
  299. break;
  300. default:
  301. LED5 = 0; LED6 = 0; LED7 = 0; LED8 = 0; LED9 = 0; LED10 = 0; LED11 = 0;
  302. LED12 = 0; LED13 = 0; LED14 = 0; LED15 = 0;
  303. break;
  304. }
  305. delay_ms(20); //任务调度
  306. }
  307. }
  308. //按键检测任务
  309. void keyG_task(void *pdata)
  310. {
  311. pdata=pdata;
  312. NVIC_InitTypeDef NVIC_InitStructure;
  313. while (1)
  314. {
  315. if (flag_Exit == 1)
  316. {
  317. NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;//外部中断4
  318. NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;//使能外部中断通道
  319. NVIC_Init(&NVIC_InitStructure);//配置
  320. PB4_Num++;
  321. OSMboxPost(msg_TaskC, &PB4_Num); //发送邮箱消息
  322. delay_ms(500);
  323. NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;//外部中断4
  324. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
  325. NVIC_Init(&NVIC_InitStructure);//配置
  326. flag_Exit = 0;
  327. }
  328. }
  329. }
  330. //外部中断4服务程序---由PB4下降沿触发
  331. //中断服务程序不能调用可能会导致任务调度的函数
  332. void EXTI4_IRQHandler(void)
  333. {
  334. OSIntEnter(); //进入中断处理
  335. flag_Exit = 1;
  336. EXTI_ClearITPendingBit(EXTI_Line4);//清除LINE4上的中断标志位
  337. OSIntExit(); //退出中断处理
  338. }
  339. //定时器3中断服务函数
  340. void TIM3_IRQHandler(void)
  341. {
  342. OSIntEnter(); //进入中断处理
  343. if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
  344. {
  345. LED0=!LED0;//LED0翻转
  346. taskA_Num++;
  347. }
  348. TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
  349. OSIntExit(); //退出中断处理
  350. }