Use time slice to implement multi-task SCM code

Source: Internet
Author: User
Tags time 0
There are four functional modules to be implemented: IR signal decoding, repeated standby signal button judgment, I2C device interruption processing, led & keypad scanning. In addition to the I2C device interrupt processing, the timer is required for the four modules. Unfortunately, the single-chip microcomputer we use is ht46r22 and there is only one timer. Based on the concept of time slice in the operating system, I finally wrote the code that I still think is perfect. From the test results, the modules do not interfere with each other and work well. Before the time slice is used, the LED will flash when the IR signal arrives, so that timer will be interrupted every time the IR signal arrives, and the scanning of LED & keypad depends on timer scheduling, so it will naturally flash ). However, the time slice is used to decode the IR signal. A major drawback is that when the pulse width is calculated, the error value range is too large-to reach the size of a time slice. After writing this code, I also wrote a task schedule and message box for single-chip microcomputer. Simply put, a layer is encapsulated in this program, implementing insert_task_2_queue () and schedule_task () and so on. Unfortunately, the simulator will be returned to HT when it expires. This code has been roughly completed, but has not been debugged yet. Please keep it for now. I will not elaborate on the Code and the principles of each module here, because it involves a wide range of aspects, but I cannot talk about it. If you need to understand this Code and are confused, feel free to contact me by email. In addition, do not blame the electronic engineers for using global variables, rather than using arrays. I used to do that until I used the HT-IDE 3000 development platform, which does not support static variables, pointers, no malloc and free. What's more, the most important thing about MCU programs is stability, especially when you are dealing with OTP (one-time programming) chips.
//Ht46r22.c////Body: Ht46r22////Mask option following://SysVolt: 5.0V//SysFreq: 8000KHz//Wake-up PA0-7: All Non-Wake-up//Pull-high PA0-5: All Pull-high//IIC: Enable//Pull-high PB: Pull-high//Pull-high PC: Pull-high//Pull_high PD: Pull-high//the others use the default value#include <Ht46r22.h>/********************************* BASIC TYPE ********************************/#define uint8_t unsigned char#define uint16_t unsigned long/********************************* IR SIGNAL *********************************/#define crystal 8000000 // Crystal frequency#define PSC 16 // Prescaler stage#define nMS 0.25 // Timer interval: 0.25ms#define MS_IR_LEADER 5.44 // Leader code: 5.44ms#define MS_IR_CODE_0 0.76 // Code-0: 0.76ms,=(0.25ms * 3)#define MS_IR_CODE_1 1.73 // Code-1: 1.73ms,=(0.25ms * 7)#define IR_CUSTOM_CODE1 (0x80) // customer-code 1, Need convert BIT7~0 to bit0~7#define IR_CUSTOM_CODE2 (0xff) // customer-code 2#define IR_CUSTOM_CODE3 (0xff) // customer-code 3#define IR_CUSTOM_CODE4 (0x80) // customer-code 4#define IR_KEYVALUE_PWR1 (0x46) // standby-code 1 #define IR_KEYVALUE_PWR2 (0x31) // standby-code 2/********************************* TMR VALUE *********************************/#define TMR_nMS 0x82 // (0xff-((nMS*crystal/1000)/PSC)) Timer value for timing 0.25ms#define TMR_IR_0_nTIMES 3 // Code-0: 0.76ms=0.25ms*3#define TMR_IR_1_nTIMES 7 // Code-1: 1.73ms=0.25ms*7#define TMR_IR_SCALE 1 // Error rangeuint8_t tmr_ir_decode; uint8_t tmr_ir_repeat;uint8_t tmr_led_refresh;/********************************* IR DECODE *********************************/#define IR_FRAME_BITS 48 // Total bits of one frame data #define IR_FRAME_BYTES (IR_FRAME_BITS/8) // Length of one frame datauint8_t ir_bits_cnt; // Counter for data bitsuint8_t ir_data[IR_FRAME_BYTES];// Ir data bufferuint8_t ir_data_ptr;bit ir_data_ready; // 1-Data be ready/********************************** PIN DEF **********************************/#define STANDBY _pc0#define LOCK _pd0/******************************** STANDBY DEF ********************************/uint8_t pwr_repeat_cnt;bit pwr_flag;/********************************** CMD DEF **********************************/#define I2C_CMD_LED 0x80 // Led Refresh Command#define I2C_CMD_LOCK 0x40 // LOCK Refresh Commanduint8_t i2c_cmd; // Commandword: rx_data[0]/********************************** LED DEF **********************************/#define LED_NUM 4 #define LED_SET_DATA(x) do{_pbc = 0x00; _pb = x;}while(0)#define LED_EN_COM(x) do{_pa |= 0x0f; _pa &= ~(1<<(x));}while(0)#define LED_DIS_ALL_COMS() do{_pa |= 0x0f;}while(0)    bit lock_status; // LOCK-Led status: rx_data[1]uint8_t led_data[LED_NUM]; // Led display data buffer: rx_data[1:4]uint8_t refresh_timeslice; // Refresh timeslice/********************************** I2C DEF **********************************/#define I2C_SLAVE_ADDR 0x0c#define RX_LEN (LED_NUM+1) // commandword + data[0] + data[1] + data[2] + data[3]uint8_t tx_data; uint8_t rx_data[RX_LEN];uint8_t rx_data_ptr;/***************************** interrupt vector ******************************/#pragma vector isr_ext @ 0x4#pragma vector isr_tmr @ 0x8#pragma vector isr_i2c @ 0x10/******************************* PRIVATE FUNC ********************************/uint8_t byte_reverse(uint8_t dat){    /* Convert bit[7:0] to bit[0:7] */        uint8_t i;    uint8_t src, dsn;    src = dat;    dsn = src & 0x1;;    for(i = 0; i < 7; i++) {        src >>= 1; dsn <<= 1;        dsn |= src & 0x1;    }    return dsn;}/************************************ ISR ************************************/void isr_ext(){    /* External ISR */        /* Interval between two external interrupt triggered by falling edge of ir-signal. */    uint8_t int_interval;     int_interval = tmr_ir_decode;    tmr_ir_decode = 0;          //decode ir signal    if ((int_interval >= (TMR_IR_1_nTIMES-TMR_IR_SCALE))         && (int_interval <= (TMR_IR_1_nTIMES+TMR_IR_SCALE))) {        // Code 1        if (ir_data_ptr == IR_FRAME_BYTES) ir_data_ptr = 0;        ir_data[ir_data_ptr] = (ir_data[ir_data_ptr]<<1) + 1;        ir_bits_cnt++;        if ((ir_bits_cnt%8) == 0) ir_data_ptr++;    }    else if ((int_interval >= (TMR_IR_0_nTIMES-TMR_IR_SCALE))         && (int_interval <= (TMR_IR_0_nTIMES+TMR_IR_SCALE))) {        // Code 0        if (ir_data_ptr == IR_FRAME_BYTES) ir_data_ptr = 0;        ir_data[ir_data_ptr] = (ir_data[ir_data_ptr]<<1);        ir_bits_cnt++;        if ((ir_bits_cnt%8) == 0) ir_data_ptr++;    }    else {        // Other, invalid signal, reset        ir_data_ptr = 0;        ir_bits_cnt = 0;        ir_data_ready = 0;    }    if (ir_bits_cnt == IR_FRAME_BITS) {        // Receive over, set ir_data_ready        ir_data_ptr = 0;        ir_bits_cnt = 0;        ir_data_ready = 1;    } } void isr_tmr(){    /* Timer ISR, time 0.25ms */        // Check ir repeat. Repeat interval=0.25ms*200*6    tmr_ir_repeat++;    if (tmr_ir_repeat > 200) {        // time 50ms, 50ms = 200*0.25ms        tmr_ir_repeat = 0;        if (pwr_flag) {            pwr_repeat_cnt++;            if( pwr_repeat_cnt >= 6 ) pwr_flag = 0;        }    }        // Timeslice for Led & Keypad refresh    tmr_led_refresh++;    if (tmr_led_refresh > 8) {        // time 2ms, 2ms = 8*0.25ms        tmr_led_refresh = 0;        refresh_timeslice++;        refresh_timeslice %= (LED_NUM+1);    }        // Interval for ir decoding. When ir signal coming, read it then reset it.    tmr_ir_decode++;}void isr_i2c(){     if(_haas == 1) {         // Address Match        if(_srw == 1) {            // Transmit Mode             _htx = 1;             _hdr = tx_data;         } else {            // Receive Mode       _htx = 0;       _txak = 0;       rx_data[rx_data_ptr] = _hdr;         }     } else {        // Transfer Completed         if(_htx == 1) {             // Transmitter. Continue to Transimit or Not            if(_rxak == 1) {                 _htx = 0; // _rxak=1, NO ACK                 _txak = 0;                 rx_data[rx_data_ptr] = _hdr; // Dummy read from hdr             } else {                 _hdr = tx_data; // _rxak=0; with ACK             }         } else {            // Receiver ,htx=0             rx_data[rx_data_ptr] = _hdr;            rx_data_ptr++;            if (rx_data_ptr == RX_LEN) {                // Reveive over                rx_data_ptr = 0;                // rx_data[0]is command word                i2c_cmd = rx_data[0];                switch (i2c_cmd) {                    case I2C_CMD_LED:                        // Refresh LED command,save display data                        led_data[0] = rx_data[1];                        led_data[1] = rx_data[2];                        led_data[2] = rx_data[3];                        led_data[3] = rx_data[4];                        break;                    case I2C_CMD_LOCK:                        // Refresh LOCK command, save lock_status                        lock_status = rx_data[1];                        break;                }                 _txak = 1; // end of receive             } else {                // Continue to Receive                _txak = 0;            }      }     }}/********************************* FUNCTION **********************************/void init_hw(){    /*    intc0:        +------------------------------------------------------+        |bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |        +------------------------------------------------------+        | 0   | ADF  | TF   | EIF  | EADI | ETI  | EEI  | EMI  |        +------------------------------------------------------+     */    _intc0 = 0;    /*    intc1:        +------------------------------------------------------+        |bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |        +------------------------------------------------------+        | 0   | 0    | 0    | HIF  | 0    | 0    | 0    | EHI  |        +------------------------------------------------------+     */    _intc1 = 0;        /*    tmrc:        +------------------------------------------------------+        |bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |        +------------------------------------------------------+        | TM1 | TM0  | 0    | TON  | TE   | PSC2 | PSC1 | PSC0 |        +------------------------------------------------------+         TM[1:0] = 10, timer mode,using internal fsys        PSC[2:0]= 100, PSC=16    */    _tmrc = 0x84;    _tmr = TMR_nMS;         /*    hcr:        +------------------------------------------------------+        |bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |        +------------------------------------------------------+        | HEN | 0    | 0    | HTX  | TXAK | 0    | 0    | 0    |        +------------------------------------------------------+     */    _hcr = 0;        /*        _pa[0:3]-->out, LED_COM[1:4]        _pa4 -->out, CTRL        _pa5 -->1, using for INT_        _pa[6:7]-->11, using for i2c    */    _pac = 0x20;    /*        _pb[0:7]-->out, LED    */    _pbc = 0x00;    /*        _pc0 -->out, STANDBY        _pc1 -->out, REQ    */    _pcc = 0x00;    /*        _pd0 -->out, LOCK    */    _pdc = 0x00;        _hadr = I2C_SLAVE_ADDR;    _htx = 0; // Set i2c bus to be receive mode    _txak = 0;     _hen = 1; // Enable i2c bus       _ehi = 1; // Enable i2c interrupt    _eti = 1; // Enable timer interrupt    _eei = 1; // Enable external interrupt    _emi = 1; // Enable global interrupt        _ton = 1; // Start timer}void init_sys(){    LOCK = 0; // LOCK-Led off    STANDBY = 1; // PWR-Led on        ir_data_ptr = 0;    ir_data_ready = 0;    ir_bits_cnt = 0;        tmr_ir_decode = 0;    tmr_ir_repeat = 0;    tmr_led_refresh = 0;        pwr_flag = 0;    pwr_repeat_cnt = 0;        tx_data = 0xff;    rx_data_ptr = 0;        // Leds display "boot" when system booting    led_data[0] = 0x7c;    led_data[1] = 0x5c;    led_data[2] = 0x5c;    led_data[3] = 0x78;        i2c_cmd = 0xff;    lock_status = 0;    refresh_timeslice = 0;}void main(){    uint8_t ir_custom_code[4];    uint8_t ir_keyvalue_pwr[2];        init_hw();    init_sys();        ir_custom_code[0] = byte_reverse(IR_CUSTOM_CODE1);    ir_custom_code[1] = byte_reverse(IR_CUSTOM_CODE2);    ir_custom_code[2] = byte_reverse(IR_CUSTOM_CODE3);    ir_custom_code[3] = byte_reverse(IR_CUSTOM_CODE4);    ir_keyvalue_pwr[0] = byte_reverse(IR_KEYVALUE_PWR1);    ir_keyvalue_pwr[1] = byte_reverse(IR_KEYVALUE_PWR2);        while (1) {        if (refresh_timeslice < LED_NUM) {            // Leds's turn, refresh Led display            LED_EN_COM(refresh_timeslice);            LED_SET_DATA(led_data[refresh_timeslice]);        } else {            // Keypad's turn, read keypad value            LED_DIS_ALL_COMS(); // First disable all Leds            _pb = 0xff; // Pull-High port(b)            _pbc= 0x7e; // Set port(b) to be input mode            tx_data = _pb; // Save status of port(b) to tx_data                        // Refresh LOCK-Led's status            LOCK = lock_status;        }                 if (ir_data_ready) {            // Keycode is valid?            if ((ir_data[0] == ir_custom_code[0]) && (ir_data[1] == ir_custom_code[1])                &&(ir_data[2] == ir_custom_code[2]) && (ir_data[3] == ir_custom_code[3])                &&(ir_data[4] == ir_keyvalue_pwr[0])&& (ir_data[5] == ir_keyvalue_pwr[1])) {                // Check whether Key-PWR is pressed repeatedly.                 if (pwr_flag == 0) {                    STANDBY = ~STANDBY;                                        if (STANDBY == 1) {                        // System on,Leds display "boot"                        led_data[0] = 0x7c;                        led_data[1] = 0x5c;                        led_data[2] = 0x5c;                        led_data[3] = 0x78;                    } else {                        // System off,Leds display "----",LOCK-Led off                        led_data[0] = led_data[1]= led_data[2] = led_data[3] = 0x40;                        lock_status = 0;                    }                }                 pwr_flag = 1; pwr_repeat_cnt = 0;            }                        ir_data_ready = 0;        }            }    }

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.