织梦CMS - 轻松建站从此开始!

罗索

应用时间片实现多任务的单片机代码

jackyhwei 发布于 2011-07-18 21:16 点击:次 
要实现的功能模块有四个:ir信号解码,待机信号重复按键判断,i2c从设备中断处理,LEDKEYPAD扫描。其中这四个模块中除了i2c从设备中断处理,其他都需要用到定时器。
TAG:

要实现的功能模块有四个:ir信号解码,待机信号重复按键判断,i2c从设备中断处理,LED&KEYPAD扫描。其中这四个模块中除了i2c从设备中断处理,其他都需要用到定时器。
 
不 巧的是,我们用到的单片机是HT46R22,只有一个定时器。我参考了操作系统时间片的概念,最终写了这个目前还觉得完美的代码。从测试结果来看,模块之 间没有互相干扰且工作良好。没采用时间片之前,ir信号到达时会导致LED闪烁,这样每次ir信号到达都会打断timer,而 LED&Keypad的扫描又依赖于timer调度,所以自然会产生闪烁现象)。但用时间片来解码ir信号,显著有一个缺点,就是脉冲宽度计算时 误差取值范围太大--达到一个时间片的大小。
 
写 完这个代码后,我还写了一个应用于单片机的task schedule和message box,简单的来说就是在这个程序上封装了一层,实现了insert_task_2_queue()和schedule_task()之类的函数。但是很 不巧,仿真器到期要归还给HT公司,这个代码虽已大致完成,但还没调试通过,这里就暂时保留吧。
 
关于代码,关于各模块原理,恕我这里不详述,因为涉及方面很广,我想谈却无从谈起。如果需要了解这份代码而又有各种困惑的,feel free to contact me by email。
 
另 外请不要轻易责怪电子工程师喜欢用全局变量,喜欢用数组而不是指针。我以前也这样,直到我用了HT-IDE 3000这个开发平台,不支持static变量,不支持指针,没有malloc和free。何况单片机程序最主要的是稳定,尤其当你面对的是OTP(一次 性编程)芯片。
 
 
  1. //Ht46r22.c 
  2. // 
  3. //Body: Ht46r22 
  4. // 
  5. //Mask option following: 
  6. //SysVolt: 5.0V 
  7. //SysFreq: 8000KHz 
  8. //Wake-up PA0-7: All Non-Wake-up 
  9. //Pull-high PA0-5: All Pull-high 
  10. //IIC: Enable 
  11. //Pull-high PB: Pull-high 
  12. //Pull-high PC: Pull-high 
  13. //Pull_high PD: Pull-high 
  14. //the others use the default value 
  15.  
  16. #include <Ht46r22.h> 
  17.  
  18. /********************************* BASIC TYPE ********************************/ 
  19. #define uint8_t unsigned char 
  20. #define uint16_t unsigned long 
  21.  
  22. /********************************* IR SIGNAL *********************************/ 
  23. #define crystal 8000000 // Crystal frequency 
  24. #define PSC 16 // Prescaler stage 
  25. #define nMS 0.25 // Timer interval: 0.25ms 
  26. #define MS_IR_LEADER 5.44 // Leader code: 5.44ms 
  27. #define MS_IR_CODE_0 0.76 // Code-0: 0.76ms,=(0.25ms * 3) 
  28. #define MS_IR_CODE_1 1.73 // Code-1: 1.73ms,=(0.25ms * 7) 
  29.  
  30. #define IR_CUSTOM_CODE1 (0x80) // customer-code 1, Need convert BIT7~0 to bit0~7 
  31. #define IR_CUSTOM_CODE2 (0xff) // customer-code 2 
  32. #define IR_CUSTOM_CODE3 (0xff) // customer-code 3 
  33. #define IR_CUSTOM_CODE4 (0x80) // customer-code 4 
  34. #define IR_KEYVALUE_PWR1 (0x46) // standby-code 1  
  35. #define IR_KEYVALUE_PWR2 (0x31) // standby-code 2 
  36.  
  37.  
  38. /********************************* TMR VALUE *********************************/ 
  39. #define TMR_nMS 0x82 // (0xff-((nMS*crystal/1000)/PSC)) Timer value for timing 0.25ms 
  40. #define TMR_IR_0_nTIMES 3 // Code-0: 0.76ms=0.25ms*3 
  41. #define TMR_IR_1_nTIMES 7 // Code-1: 1.73ms=0.25ms*7 
  42. #define TMR_IR_SCALE 1 // Error range 
  43.  
  44. uint8_t tmr_ir_decode;  
  45. uint8_t tmr_ir_repeat; 
  46. uint8_t tmr_led_refresh; 
  47.  
  48. /********************************* IR DECODE *********************************/ 
  49. #define IR_FRAME_BITS 48 // Total bits of one frame data  
  50. #define IR_FRAME_BYTES (IR_FRAME_BITS/8) // Length of one frame data 
  51. uint8_t ir_bits_cnt; // Counter for data bits 
  52. uint8_t ir_data[IR_FRAME_BYTES];// Ir data buffer 
  53. uint8_t ir_data_ptr; 
  54. bit ir_data_ready; // 1-Data be ready 
  55.  
  56. /********************************** PIN DEF **********************************/ 
  57. #define STANDBY _pc0 
  58. #define LOCK _pd0 
  59.  
  60. /******************************** STANDBY DEF ********************************/ 
  61. uint8_t pwr_repeat_cnt; 
  62. bit pwr_flag; 
  63.  
  64. /********************************** CMD DEF **********************************/ 
  65. #define I2C_CMD_LED 0x80 // Led Refresh Command 
  66. #define I2C_CMD_LOCK 0x40 // LOCK Refresh Command 
  67. uint8_t i2c_cmd; // Commandword: rx_data[0] 
  68.  
  69.  
  70. /********************************** LED DEF **********************************/ 
  71. #define LED_NUM 4  
  72. #define LED_SET_DATA(x) do{_pbc = 0x00; _pb = x;}while(0) 
  73. #define LED_EN_COM(x) do{_pa |= 0x0f; _pa &= ~(1<<(x));}while(0) 
  74. #define LED_DIS_ALL_COMS() do{_pa |= 0x0f;}while(0) 
  75.      
  76. bit lock_status; // LOCK-Led status: rx_data[1] 
  77. uint8_t led_data[LED_NUM]; // Led display data buffer: rx_data[1:4] 
  78. uint8_t refresh_timeslice; // Refresh timeslice 
  79.  
  80. /********************************** I2C DEF **********************************/ 
  81. #define I2C_SLAVE_ADDR 0x0c 
  82. #define RX_LEN (LED_NUM+1) // commandword + data[0] + data[1] + data[2] + data[3] 
  83.  
  84. uint8_t tx_data;  
  85. uint8_t rx_data[RX_LEN]; 
  86. uint8_t rx_data_ptr; 
  87.  
  88. /***************************** interrupt vector ******************************/ 
  89. #pragma vector isr_ext @ 0x4 
  90. #pragma vector isr_tmr @ 0x8 
  91. #pragma vector isr_i2c @ 0x10 
  92.  
  93. /******************************* PRIVATE FUNC ********************************/ 
  94. uint8_t byte_reverse(uint8_t dat) 
  95.     /* Convert bit[7:0] to bit[0:7] */ 
  96.      
  97.     uint8_t i; 
  98.     uint8_t src, dsn; 
  99.  
  100.     src = dat; 
  101.     dsn = src & 0x1;; 
  102.     for(i = 0; i < 7; i++) { 
  103.         src >>= 1; dsn <<= 1; 
  104.         dsn |= src & 0x1; 
  105.     } 
  106.     return dsn; 
  107.  
  108. /************************************ ISR ************************************/ 
  109. void isr_ext() 
  110.     /* External ISR */ 
  111.      
  112.     /* Interval between two external interrupt triggered by falling edge of ir-signal. */ 
  113.     uint8_t int_interval;  
  114.     int_interval = tmr_ir_decode; 
  115.     tmr_ir_decode = 0; 
  116.        
  117.     //decode ir signal 
  118.     if ((int_interval >= (TMR_IR_1_nTIMES-TMR_IR_SCALE))  
  119.         && (int_interval <= (TMR_IR_1_nTIMES+TMR_IR_SCALE))) { 
  120.         // Code 1 
  121.         if (ir_data_ptr == IR_FRAME_BYTES) ir_data_ptr = 0; 
  122.         ir_data[ir_data_ptr] = (ir_data[ir_data_ptr]<<1) + 1; 
  123.         ir_bits_cnt++; 
  124.         if ((ir_bits_cnt%8) == 0) ir_data_ptr++; 
  125.     } 
  126.     else if ((int_interval >= (TMR_IR_0_nTIMES-TMR_IR_SCALE))  
  127.         && (int_interval <= (TMR_IR_0_nTIMES+TMR_IR_SCALE))) { 
  128.         // Code 0 
  129.         if (ir_data_ptr == IR_FRAME_BYTES) ir_data_ptr = 0; 
  130.         ir_data[ir_data_ptr] = (ir_data[ir_data_ptr]<<1); 
  131.         ir_bits_cnt++; 
  132.         if ((ir_bits_cnt%8) == 0) ir_data_ptr++; 
  133.     } 
  134.     else { 
  135.         // Other, invalid signal, reset 
  136.         ir_data_ptr = 0; 
  137.         ir_bits_cnt = 0; 
  138.         ir_data_ready = 0; 
  139.     } 
  140.  
  141.     if (ir_bits_cnt == IR_FRAME_BITS) { 
  142.         // Receive over, set ir_data_ready 
  143.         ir_data_ptr = 0; 
  144.         ir_bits_cnt = 0; 
  145.         ir_data_ready = 1; 
  146.     }  
  147.   
  148. void isr_tmr() 
  149.     /* Timer ISR, time 0.25ms */ 
  150.      
  151.     // Check ir repeat. Repeat interval=0.25ms*200*6 
  152.     tmr_ir_repeat++; 
  153.     if (tmr_ir_repeat > 200) { 
  154.         // time 50ms, 50ms = 200*0.25ms 
  155.         tmr_ir_repeat = 0; 
  156.         if (pwr_flag) { 
  157.             pwr_repeat_cnt++; 
  158.             if( pwr_repeat_cnt >= 6 ) pwr_flag = 0; 
  159.         } 
  160.     } 
  161.      
  162.     // Timeslice for Led & Keypad refresh 
  163.     tmr_led_refresh++; 
  164.     if (tmr_led_refresh > 8) { 
  165.         // time 2ms, 2ms = 8*0.25ms 
  166.         tmr_led_refresh = 0; 
  167.         refresh_timeslice++; 
  168.         refresh_timeslice %= (LED_NUM+1); 
  169.     } 
  170.      
  171.     // Interval for ir decoding. When ir signal coming, read it then reset it. 
  172.     tmr_ir_decode++; 
  173.  
  174. void isr_i2c() 
  175. {  
  176.     if(_haas == 1) {  
  177.         // Address Match 
  178.         if(_srw == 1) { 
  179.             // Transmit Mode  
  180.             _htx = 1;  
  181.             _hdr = tx_data;  
  182.         } else { 
  183.             // Receive Mode  
  184.       _htx = 0;  
  185.       _txak = 0;  
  186.       rx_data[rx_data_ptr] = _hdr;  
  187.         }  
  188.     } else { 
  189.         // Transfer Completed  
  190.         if(_htx == 1) {  
  191.             // Transmitter. Continue to Transimit or Not 
  192.             if(_rxak == 1) {  
  193.                 _htx = 0; // _rxak=1, NO ACK  
  194.                 _txak = 0;  
  195.                 rx_data[rx_data_ptr] = _hdr; // Dummy read from hdr  
  196.             } else {  
  197.                 _hdr = tx_data; // _rxak=0; with ACK  
  198.             }  
  199.         } else { 
  200.             // Receiver ,htx=0  
  201.             rx_data[rx_data_ptr] = _hdr; 
  202.             rx_data_ptr++; 
  203.             if (rx_data_ptr == RX_LEN) { 
  204.                 // Reveive over 
  205.                 rx_data_ptr = 0; 
  206.                 // rx_data[0]is command word 
  207.                 i2c_cmd = rx_data[0]; 
  208.                 switch (i2c_cmd) { 
  209.                     case I2C_CMD_LED: 
  210.                         // Refresh LED command,save display data 
  211.                         led_data[0] = rx_data[1]; 
  212.                         led_data[1] = rx_data[2]; 
  213.                         led_data[2] = rx_data[3]; 
  214.                         led_data[3] = rx_data[4]; 
  215.                         break
  216.                     case I2C_CMD_LOCK: 
  217.                         // Refresh LOCK command, save lock_status 
  218.                         lock_status = rx_data[1]; 
  219.                         break
  220.                 }  
  221.                 _txak = 1; // end of receive  
  222.             } else { 
  223.                 // Continue to Receive 
  224.                 _txak = 0; 
  225.             } 
  226.       }  
  227.     } 
  228.  
  229. /********************************* FUNCTION **********************************/ 
  230. void init_hw() 
  231.     /* 
  232.     intc0: 
  233.         +------------------------------------------------------+ 
  234.         |bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | 
  235.         +------------------------------------------------------+ 
  236.         | 0   | ADF  | TF   | EIF  | EADI | ETI  | EEI  | EMI  | 
  237.         +------------------------------------------------------+  
  238.     */ 
  239.     _intc0 = 0; 
  240.     /* 
  241.     intc1: 
  242.         +------------------------------------------------------+ 
  243.         |bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | 
  244.         +------------------------------------------------------+ 
  245.         | 0   | 0    | 0    | HIF  | 0    | 0    | 0    | EHI  | 
  246.         +------------------------------------------------------+  
  247.     */ 
  248.     _intc1 = 0; 
  249.      
  250.     /* 
  251.     tmrc: 
  252.         +------------------------------------------------------+ 
  253.         |bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | 
  254.         +------------------------------------------------------+ 
  255.         | TM1 | TM0  | 0    | TON  | TE   | PSC2 | PSC1 | PSC0 | 
  256.         +------------------------------------------------------+  
  257.         TM[1:0] = 10, timer mode,using internal fsys 
  258.         PSC[2:0]= 100, PSC=16 
  259.     */ 
  260.     _tmrc = 0x84; 
  261.     _tmr = TMR_nMS;  
  262.      
  263.     /* 
  264.     hcr: 
  265.         +------------------------------------------------------+ 
  266.         |bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | 
  267.         +------------------------------------------------------+ 
  268.         | HEN | 0    | 0    | HTX  | TXAK | 0    | 0    | 0    | 
  269.         +------------------------------------------------------+  
  270.     */ 
  271.     _hcr = 0; 
  272.      
  273.     /* 
  274.         _pa[0:3]-->out, LED_COM[1:4] 
  275.         _pa4 -->out, CTRL 
  276.         _pa5 -->1, using for INT_ 
  277.         _pa[6:7]-->11, using for i2c 
  278.     */ 
  279.     _pac = 0x20; 
  280.     /* 
  281.         _pb[0:7]-->out, LED 
  282.     */ 
  283.     _pbc = 0x00; 
  284.     /* 
  285.         _pc0 -->out, STANDBY 
  286.         _pc1 -->out, REQ 
  287.     */ 
  288.     _pcc = 0x00; 
  289.     /* 
  290.         _pd0 -->out, LOCK 
  291.     */ 
  292.     _pdc = 0x00; 
  293.      
  294.     _hadr = I2C_SLAVE_ADDR; 
  295.     _htx = 0; // Set i2c bus to be receive mode 
  296.     _txak = 0;  
  297.     _hen = 1; // Enable i2c bus 
  298.     
  299.     _ehi = 1; // Enable i2c interrupt 
  300.     _eti = 1; // Enable timer interrupt 
  301.     _eei = 1; // Enable external interrupt 
  302.     _emi = 1; // Enable global interrupt 
  303.      
  304.     _ton = 1; // Start timer 
  305.  
  306.  
  307. void init_sys() 
  308.     LOCK = 0; // LOCK-Led off 
  309.     STANDBY = 1; // PWR-Led on 
  310.      
  311.     ir_data_ptr = 0; 
  312.     ir_data_ready = 0; 
  313.     ir_bits_cnt = 0; 
  314.      
  315.     tmr_ir_decode = 0; 
  316.     tmr_ir_repeat = 0; 
  317.     tmr_led_refresh = 0; 
  318.      
  319.     pwr_flag = 0; 
  320.     pwr_repeat_cnt = 0; 
  321.      
  322.     tx_data = 0xff; 
  323.     rx_data_ptr = 0; 
  324.      
  325.     // Leds display "boot" when system booting 
  326.     led_data[0] = 0x7c; 
  327.     led_data[1] = 0x5c; 
  328.     led_data[2] = 0x5c; 
  329.     led_data[3] = 0x78; 
  330.      
  331.     i2c_cmd = 0xff; 
  332.     lock_status = 0; 
  333.     refresh_timeslice = 0; 
  334.  
  335. void main() 
  336.     uint8_t ir_custom_code[4]; 
  337.     uint8_t ir_keyvalue_pwr[2]; 
  338.      
  339.     init_hw(); 
  340.     init_sys(); 
  341.      
  342.     ir_custom_code[0] = byte_reverse(IR_CUSTOM_CODE1); 
  343.     ir_custom_code[1] = byte_reverse(IR_CUSTOM_CODE2); 
  344.     ir_custom_code[2] = byte_reverse(IR_CUSTOM_CODE3); 
  345.     ir_custom_code[3] = byte_reverse(IR_CUSTOM_CODE4); 
  346.     ir_keyvalue_pwr[0] = byte_reverse(IR_KEYVALUE_PWR1); 
  347.     ir_keyvalue_pwr[1] = byte_reverse(IR_KEYVALUE_PWR2); 
  348.      
  349.     while (1) { 
  350.         if (refresh_timeslice < LED_NUM) { 
  351.             // Leds's turn, refresh Led display 
  352.             LED_EN_COM(refresh_timeslice); 
  353.             LED_SET_DATA(led_data[refresh_timeslice]); 
  354.         } else { 
  355.             // Keypad's turn, read keypad value 
  356.             LED_DIS_ALL_COMS(); // First disable all Leds 
  357.             _pb = 0xff; // Pull-High port(b) 
  358.             _pbc= 0x7e; // Set port(b) to be input mode 
  359.             tx_data = _pb; // Save status of port(b) to tx_data 
  360.              
  361.             // Refresh LOCK-Led's status 
  362.             LOCK = lock_status; 
  363.         }  
  364.          
  365.         if (ir_data_ready) { 
  366.             // Keycode is valid? 
  367.             if ((ir_data[0] == ir_custom_code[0]) && (ir_data[1] == ir_custom_code[1]) 
  368. &&(ir_data[2] == ir_custom_code[2]) && (ir_data[3] == ir_custom_code[3]) 
  369. &&(ir_data[4] == ir_keyvalue_pwr[0])&& (ir_data[5] == ir_keyvalue_pwr[1])) { 
  370. // Check whether Key-PWR is pressed repeatedly.  
  371.                 if (pwr_flag == 0) { 
  372.                     STANDBY = ~STANDBY; 
  373.                     if (STANDBY == 1) { 
  374.                         // System on,Leds display "boot" 
  375.                         led_data[0] = 0x7c; 
  376.                         led_data[1] = 0x5c; 
  377.                         led_data[2] = 0x5c; 
  378.                         led_data[3] = 0x78; 
  379.                     } else { 
  380.                         // System off,Leds display "----",LOCK-Led off 
  381.                         led_data[0] = led_data[1]= led_data[2] = led_data[3] = 0x40; 
  382.                         lock_status = 0; 
  383.                     } 
  384.                 }  
  385.                 pwr_flag = 1; pwr_repeat_cnt = 0; 
  386.             }
  387.             ir_data_ready = 0; 
  388.         } 
  389.     } 

 

(sepnic)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201107/14726.html]
本文出处:CSDN博客 作者:sepnic
顶一下
(1)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容