久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6339|回復: 0
收起左側

應用時間片實現多任務的單片機代碼

[復制鏈接]
ID:80436 發表于 2015-5-21 01:14 | 顯示全部樓層 |閱讀模式
要實現的功能模塊有四個: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(一次性編程)芯片。

view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
//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 range  

uint8_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 data  
uint8_t ir_bits_cnt; // Counter for data bits  
uint8_t ir_data[IR_FRAME_BYTES];// Ir data buffer  
uint8_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 Command  
uint8_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;  
        }  

    }  

}  

回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产精品美女久久久久久免费 | 免费在线精品视频 | 亚洲444eee在线观看 | 国产精品自产拍在线观看蜜 | 国产精品成人av | 亚洲第一视频 | 欧美xxxx性 | 91精品国产综合久久福利软件 | 欧美网址在线观看 | 久久国产精品精品国产色婷婷 | 欧美成人精品在线 | 欧美在线看片 | 91av视频在线 | 精品国产欧美一区二区三区成人 | 国产 欧美 日韩 一区 | 久久久久国产精品一区二区 | 国产乱码精品一区二三赶尸艳谈 | 日本欧美国产在线 | 亚洲最大av网站 | 日韩高清国产一区在线 | 毛片一区| 久久狼人天堂 | av二区三区| 在线播放国产一区二区三区 | 欧美亚洲高清 | 亚洲欧美一区二区在线观看 | 999国产视频| 欧美在线国产精品 | 黄网站在线播放 | 国产精品久久久久久久免费大片 | 中文字幕亚洲精品 | 一区二区在线免费观看 | 日本三级在线 | 日韩第一夜 | 亚洲欧美日韩国产综合 | 亚洲婷婷六月天 | 久久精品国产99国产精品 | 日本一卡精品视频免费 | 午夜在线小视频 | 国产成人免费视频网站视频社区 | 久久视频精品 |