remote.c 16 KB

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