remote.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /*
  2. +-----------------------
  3. |
  4. | 红外自学习遥控
  5. |
  6. | Chang Logs:
  7. | Date Author Notes
  8. | 2010-01-02 aozima The bate version.
  9. +----------------------------------------------------
  10. */
  11. #include <rtthread.h>
  12. #include <dfs_posix.h>
  13. #include <stm32f10x.h>
  14. /* 设置允许偏差,单位0.01ms */
  15. #define remote_deviation 15
  16. #define remote_code_len_max 100
  17. /* 红外模式 0:没启动,1:自学习,2:正常解码 */
  18. unsigned int rem_mode = 0;
  19. static unsigned int first_tick = 0;
  20. static unsigned int rx_count = 0;
  21. static unsigned short rm_code[remote_code_len_max];
  22. struct rem_codes_typedef
  23. {
  24. unsigned int len;
  25. unsigned short rem_code[remote_code_len_max];
  26. };
  27. struct rem_codes_typedef * p_rem_code_src = RT_NULL;
  28. static const char str1[]="KEY_UP"; /* 上 */
  29. static const char str2[]="KEY_DOWN"; /* 下 */
  30. static const char str3[]="KEY_LEFT"; /* 左 */
  31. static const char str4[]="KEY_RIGHT"; /* 右 */
  32. static const char str5[]="KEY_ENTER"; /* 确认 */
  33. static const char str6[]="KEY_RETURN"; /* 返回 */
  34. static const char * desc_key[6]= {str1,str2,str3,str4,str5,str6};
  35. /* tim5 configure */
  36. static void TIM5_Configuration(void)
  37. {
  38. /* 时钟及分频设置 */
  39. {
  40. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  41. /* Time Base configuration */
  42. /* 72M/720 = 0.01ms */
  43. TIM_TimeBaseStructure.TIM_Prescaler = 720-1;
  44. //计数模式:向上计数
  45. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  46. TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
  47. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  48. //重新计数的起始值
  49. TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  50. TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
  51. }
  52. /* 捕获设置 */
  53. {
  54. TIM_ICInitTypeDef TIM_ICInitStructure;
  55. TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;/* 每次检测到捕获输入就触发一次捕获 */
  56. TIM_ICInitStructure.TIM_ICFilter = 8;/* 滤波 */
  57. TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;//选择通道3
  58. TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;//下降沿
  59. TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//通道方向选择
  60. TIM_ICInit(TIM5, &TIM_ICInitStructure);
  61. TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;//选择通道3
  62. TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿
  63. TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_IndirectTI;//通道方向选择
  64. TIM_ICInit(TIM5, &TIM_ICInitStructure);
  65. }
  66. /* 输入触发源选择:外部输入触发 */
  67. TIM_SelectInputTrigger(TIM5, TIM_TS_ETRF);//TIM_TS_ETRF 外部触发
  68. /* 从模式-复位模式 */
  69. /* TIM_SlaveMode_Reset 4:选中的触发输入(TRGI)的上升沿重新初始化计数器,并且产生一个更新寄存器的信号 */
  70. TIM_SelectSlaveMode(TIM5, TIM_SlaveMode_Reset);
  71. TIM_SelectMasterSlaveMode(TIM5, TIM_MasterSlaveMode_Enable);
  72. /* TIM enable counter */
  73. TIM_Cmd(TIM5, ENABLE);
  74. /* Enable the CC3 and CC4 Interrupt Request */
  75. TIM_ITConfig(TIM5, TIM_IT_CC3, ENABLE);
  76. TIM_ITConfig(TIM5, TIM_IT_CC4, ENABLE);
  77. }
  78. static void NVIC_Configuration(void)
  79. {
  80. NVIC_InitTypeDef NVIC_InitStructure;
  81. /* Enable the TIM5 global Interrupt */
  82. NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
  83. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  84. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  85. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  86. NVIC_Init(&NVIC_InitStructure);
  87. }
  88. static void RCC_Configuration(void)
  89. {
  90. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
  91. /* TIM5 clock enable */
  92. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
  93. /* clock enable */
  94. RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA ,ENABLE);
  95. }
  96. static void GPIO_Configuration(void)
  97. {
  98. GPIO_InitTypeDef GPIO_InitStructure;
  99. /* TIM5 channel 3 pin (PA.02) configuration */
  100. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
  101. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  102. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  103. GPIO_Init(GPIOA, &GPIO_InitStructure);
  104. }
  105. void rem_start(void)
  106. {
  107. RCC_Configuration();
  108. GPIO_Configuration();
  109. /* configure TIM5 for remote and encoder */
  110. NVIC_Configuration();
  111. TIM5_Configuration();
  112. p_rem_code_src = rt_malloc( sizeof(struct rem_codes_typedef)*6 );
  113. rt_memset(p_rem_code_src,0, sizeof(struct rem_codes_typedef)*6 );
  114. /* 解读红外信息 */
  115. {
  116. int fd,size;
  117. char buf[7];/* 文件读取临时缓存 #####\r\n */
  118. unsigned int i;
  119. unsigned short tmp;
  120. unsigned int read_index = 0;
  121. unsigned int EOF_flag = 1;
  122. rt_kprintf("\r\n解读红外信息");
  123. fd = open("/resource/remote.txt",O_RDONLY,0);
  124. if( fd>0 )
  125. {
  126. rt_kprintf("\r/resource/remote.txt打开成功");
  127. while( EOF_flag )
  128. {
  129. /* 读取长度 */
  130. size = read(fd,buf,7);
  131. if( (size == 7) && (buf[5]=='\r') && buf[6]=='\n' )
  132. {
  133. /* 转换得到样本数据长度 */
  134. tmp = (buf[0]-'0')*10000
  135. + (buf[1]-'0')*1000
  136. + (buf[2]-'0')*100
  137. + (buf[3]-'0')*10
  138. + (buf[4]-'0');
  139. if( tmp<100 )
  140. {
  141. unsigned int code_len = tmp;
  142. p_rem_code_src[read_index].len = code_len;
  143. /* 如果样本长度符合 就开始从文件读取编码数据 */
  144. for(i=0; i<code_len; i++)
  145. {
  146. size = read(fd,buf,7);
  147. if( (size == 7) && (buf[5]=='\r') && buf[6]=='\n' )
  148. {
  149. /* 转换得到样本数据 */
  150. tmp = (buf[0]-'0')*10000
  151. + (buf[1]-'0')*1000
  152. + (buf[2]-'0')*100
  153. + (buf[3]-'0')*10
  154. + (buf[4]-'0');
  155. p_rem_code_src[read_index].rem_code[i] = tmp;
  156. }
  157. }
  158. read_index++;
  159. }
  160. }
  161. else
  162. {
  163. EOF_flag = 0;
  164. }
  165. }//while( EOF_flag )
  166. /* 判断是否正确解读编码数据文件 */
  167. if ( p_rem_code_src[0].len > 0 && p_rem_code_src[0].len < remote_code_len_max )
  168. {
  169. /* 设置工作模式为正常识别模式 */
  170. rem_mode = 2;
  171. rt_kprintf("\r红外遥控编码文件解读完成,已打开红外遥控功能\r\n");
  172. }
  173. else
  174. {
  175. /* 设置工作模式为正常识别模式 */
  176. rem_mode = 0;
  177. rt_kprintf("\r\n红外遥控编码文件解读失败,已关闭红外遥控功能\r\n");
  178. }
  179. }
  180. else
  181. {
  182. rt_kprintf("\r红外遥控编码文件 /resource/remote.txt 打开失败! fd:%d\r\n无法开启红外遥控功能.\r\n请执行rem_study()进行自动学习\r\n",fd);
  183. }
  184. close(fd);
  185. }/* 解读红外信息 */
  186. }
  187. #include <rtgui/event.h>
  188. void rem_encoder(struct rtgui_event_kbd * p)
  189. {
  190. struct rtgui_event_kbd * p_kbd_event = p;
  191. /* 检查是否有数据被捕获 */
  192. if( (rem_mode==2) && (rt_tick_get()>first_tick+10) && (rx_count > 0) )
  193. {
  194. /* 手动清零第一个捕获结果 */
  195. rm_code[0] = 0;
  196. rx_count = 0;
  197. /* 匹配捕获的数据 */
  198. {
  199. unsigned int tmp;
  200. unsigned int err_flag = 0;
  201. unsigned int rem_cmp_n = 6;
  202. /* 循环匹配所有KEY */
  203. while( rem_cmp_n )
  204. {
  205. unsigned int tmp2 = p_rem_code_src[ 6-rem_cmp_n ].len;
  206. //rt_kprintf("\r\nrem_cmp_n:%d tmp2:%d",rem_cmp_n,tmp2);
  207. if( tmp2 )
  208. {
  209. for(tmp=0; tmp<tmp2; tmp++)
  210. {
  211. /* 判断捕获结果是否在偏差允许范围内 */
  212. if( !( (rm_code[tmp] < p_rem_code_src[6-rem_cmp_n].rem_code[tmp]+remote_deviation)
  213. && (rm_code[tmp] > p_rem_code_src[6-rem_cmp_n].rem_code[tmp]-remote_deviation)) )
  214. {
  215. err_flag = 1;
  216. }
  217. }
  218. }
  219. else
  220. {
  221. err_flag = 1;
  222. rt_kprintf("\r\n解码失败");
  223. }
  224. if( err_flag==0 )
  225. {
  226. /* 对比全部数据符合 */
  227. rt_kprintf("\r\n识别到遥控按键 %s",desc_key[6-rem_cmp_n]);
  228. switch( rem_cmp_n )
  229. {
  230. case 6:
  231. p_kbd_event->key = RTGUIK_UP;
  232. break;
  233. case 5:
  234. p_kbd_event->key = RTGUIK_DOWN;
  235. break;
  236. case 4:
  237. p_kbd_event->key = RTGUIK_LEFT;
  238. break;
  239. case 3:
  240. p_kbd_event->key = RTGUIK_RIGHT;
  241. break;
  242. case 2:
  243. p_kbd_event->key = RTGUIK_RETURN;
  244. break;
  245. case 1:
  246. p_kbd_event->key = RTGUIK_HOME;
  247. break;
  248. default:
  249. break;
  250. }
  251. rem_cmp_n = 0;
  252. }
  253. else
  254. {
  255. /* 对比不符合,清零错误标致,以进行下一次对比 */
  256. err_flag = 0;
  257. rem_cmp_n --;
  258. }
  259. }
  260. }
  261. }//红外遥控匹配
  262. }
  263. /* remote isr */
  264. void remote_isr(void)
  265. {
  266. static unsigned int clr_flag = 1;
  267. unsigned int tick_now = rt_tick_get();
  268. /* 红外遥控下降沿 */
  269. if(TIM_GetITStatus(TIM5, TIM_IT_CC3) == SET)
  270. {
  271. switch( rem_mode )
  272. {
  273. case 0://未启动
  274. break;
  275. case 1://自学习
  276. if( (rx_count==0) || (rx_count>90) || (tick_now>first_tick+10) )
  277. {
  278. //需要清0
  279. rx_count = 0;
  280. clr_flag = 1;
  281. }
  282. if( rx_count < remote_code_len_max )
  283. {
  284. rm_code[rx_count++] = TIM_GetCapture3(TIM5);
  285. }
  286. break;
  287. case 2://正常解码
  288. if( (rx_count>90) || tick_now>first_tick+10 )
  289. {
  290. rx_count = 0;
  291. clr_flag = 1;
  292. }
  293. if(rx_count < remote_code_len_max )
  294. {
  295. rm_code[rx_count++] = TIM_GetCapture3(TIM5);
  296. }
  297. break;
  298. default:
  299. rem_mode = 0;//设置模式为未启动
  300. break;
  301. }
  302. TIM_ClearITPendingBit(TIM5, TIM_IT_CC3);
  303. }
  304. /* 红外遥控上升沿 */
  305. if(TIM_GetITStatus(TIM5, TIM_IT_CC4) == SET)
  306. {
  307. switch( rem_mode )
  308. {
  309. case 0://未启动
  310. break;
  311. case 1://自学习
  312. if( rx_count < remote_code_len_max )
  313. {
  314. rm_code[rx_count++] = TIM_GetCapture4(TIM5);
  315. }
  316. break;
  317. case 2://正常解码
  318. if( rx_count < remote_code_len_max )
  319. {
  320. rm_code[rx_count++] = TIM_GetCapture4(TIM5);
  321. }
  322. break;
  323. default:
  324. rem_mode = 0;//设置模式为未启动
  325. break;
  326. }
  327. TIM_ClearITPendingBit(TIM5, TIM_IT_CC4);
  328. }
  329. //更新时间戳
  330. first_tick = tick_now;
  331. //检测是否需要重置计数器
  332. if( clr_flag )
  333. {
  334. //重置计数器
  335. TIM_SetCounter(TIM5,0);
  336. clr_flag = 0;
  337. }
  338. }
  339. #include <finsh.h>
  340. /* 启动红外学习程序 */
  341. int rem_study(void)
  342. {
  343. unsigned int i;
  344. int fd,size;
  345. unsigned char tmp_buf[ (remote_code_len_max+1)*7 ];
  346. rem_mode = 1;
  347. rx_count = 0;
  348. rt_kprintf("\r\n红外遥控自学习功能启动");
  349. fd = open("/resource/remote.txt",O_WRONLY | O_TRUNC,0);
  350. if( !(fd<0) )
  351. {
  352. rt_kprintf("\r\n红外遥控编码文件 /resource/remote.txt 创建成功");
  353. }
  354. else
  355. {
  356. rt_kprintf("\r红外遥控编码文件 /resource/remote.txt 创建失败.\r\n学习程序中止.");
  357. return -1;
  358. }
  359. /* 学习6个键盘 */
  360. for( i=0; i<6; i++)
  361. {
  362. unsigned int is_ok = 1;
  363. rt_kprintf("\r\npress key %s",desc_key[i]);
  364. while( is_ok==1 )
  365. {
  366. if( (rem_mode==1) && (rt_tick_get()>first_tick+10) && (rx_count > 0) )
  367. {
  368. unsigned int a,b;
  369. unsigned char * p = tmp_buf;
  370. rt_kprintf("\r\n%s",desc_key[i]);
  371. b = rx_count;
  372. p_rem_code_src[i].len = rx_count;
  373. /* TIM disable counter */
  374. TIM_Cmd(TIM5, DISABLE);
  375. /* disable the CC3 and CC4 Interrupt Request */
  376. TIM_ITConfig(TIM5, TIM_IT_CC3, DISABLE);
  377. TIM_ITConfig(TIM5, TIM_IT_CC4, DISABLE);
  378. p[0] = rx_count / 10000 +'0';
  379. rx_count = rx_count % 10000;
  380. p[1] = rx_count / 1000 +'0';
  381. rx_count = rx_count % 1000;
  382. p[2] = rx_count / 100 +'0';
  383. rx_count = rx_count % 100;
  384. p[3] = rx_count / 10 +'0';
  385. rx_count = rx_count % 10;
  386. p[4] = rx_count +'0';
  387. rx_count = 0;
  388. p[5] = '\r';
  389. p[6] = '\n';
  390. p += 7;
  391. rm_code[0] = 0;
  392. for( a=0; a<b; a++)
  393. {
  394. /* 把当前数据直接写进样品数据 */
  395. p_rem_code_src[i].rem_code[a] = rm_code[a];
  396. /* 然后转换成文本格式 #####\r\n */
  397. p[0] = rm_code[a] / 10000 +'0';
  398. rm_code[a] = rm_code[a] % 10000;
  399. p[1] = rm_code[a] / 1000 +'0';
  400. rm_code[a] = rm_code[a] % 1000;
  401. p[2] = rm_code[a] / 100 +'0';
  402. rm_code[a] = rm_code[a] % 100;
  403. p[3] = rm_code[a] / 10 +'0';
  404. rm_code[a] = rm_code[a] % 10;
  405. p[4] = rm_code[a] +'0';
  406. p[5] = '\r';
  407. p[6] = '\n';
  408. p += 7;
  409. }
  410. size = write(fd,(char*)tmp_buf,(b+1)*7 );
  411. if( size==((b+1)*7) )
  412. {
  413. rt_kprintf("文件写入成功");
  414. is_ok++;
  415. rt_thread_delay( 2 );
  416. /* 重新打开 TIM5 进行捕获 */
  417. TIM_ClearITPendingBit(TIM5, TIM_IT_CC3);
  418. TIM_ClearITPendingBit(TIM5, TIM_IT_CC4);
  419. /* TIM ENABLE counter */
  420. TIM_Cmd(TIM5, ENABLE);
  421. /* ENABLE the CC3 and CC4 Interrupt Request */
  422. TIM_ITConfig(TIM5, TIM_IT_CC3, ENABLE);
  423. TIM_ITConfig(TIM5, TIM_IT_CC4, ENABLE);
  424. }
  425. else
  426. {
  427. rt_kprintf("文件写入失败\r\n红外学习程序退出");
  428. return -1;
  429. }
  430. }
  431. rt_thread_delay(1);
  432. }//while( is_ok==1 )
  433. }//for( i=0; i<6; i++)
  434. close(fd);
  435. rt_kprintf("\r\n学习完成,现在进入正常识别模式\r\n");
  436. rem_mode = 2;
  437. return 0;
  438. }
  439. FINSH_FUNCTION_EXPORT(rem_study, rem_study);