⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 test.c

📁 用51单片机开发的简单计算器程序
💻 C
字号:
#include "calc.h"
bit shift_flag;
sbit sck = P2^0;
sbit load = P2^1;
sbit d_out = P2^2;
sbit sign_led = P2^3;
sbit shift_led = P2^4;
float calc_res = 0;
const byte kb_table[16] = {     
    1, 2, 3, '+',
    4, 5, 6, '-',
    7, 8, 9, '*',
    's', 0, '.', '='
};
const byte s_kb_table[16] = {
    1, 2, 3, 's',
    4, 5, 6, '-',
    7, 8, 9, 'C',
    '/', 0, '.', '='
};
byte current_digs[4] = {0x7f,0x7f,0x7f,0x7f};

float sqrt(float val){
    float root = val/2;
    float check, n, m;
    check=root*root;
    n = 0; m = val;
    while (check-val<-0.0001 || check-val>0.0001){
        if (check > val){
            m = root;
            root = (root + n) / 2;
        } else {
            n = root;
            root = (root + m) / 2;
        }
        check = root * root;
    }
    return root;
}

/**
 * kb_scan will scan the keyboad (4*4) at the port: kb_port, and return
 * the key value, according to key value tables.
 */
byte kb_scan(){
	#define kb_port P3
    #define READ_MSK 0x0f
    byte col_val = 0x0f;
    byte scan_msk = 0x10;
    byte test_msk = 0x01;
    byte i = 0;
    byte j = 0;
    byte result = 0;
    while(col_val == 0x0f){
        kb_port = READ_MSK; // read on lower 4 bits.
        col_val = kb_port;
        col_val &= READ_MSK;
    }
    for (i=0; i<4; i++){        // scanning row i.
        kb_port = (~scan_msk);    // activate one row only.
        col_val = kb_port;
        col_val &= READ_MSK;
		test_msk = 0x01;
        for (j=0; j<4; j++){    // scanning col j.
            if ((col_val & test_msk) == 0){
                // have input on this col.
                result = ((shift_flag==1) ? s_kb_table[j*4+i]:kb_table[j*4+i]);
                goto start_wait;
            }
            test_msk <<=1;
        }
        scan_msk <<= 1;
    }
start_wait:
    while(col_val != 0x0f){
        kb_port = READ_MSK; // read on lower 4 bits.
        col_val = kb_port;
        col_val &= READ_MSK;
    }
	return result;
}
/**
 * send_word will send two byte of data using SCK, LOAD and D_OUT 3
 * ports to MAX7219 numeric LED driver. The first byte shall be address
 * while the second byte will the data.
 */
void send_word(byte addr, byte val){
    byte i;
    byte comm_msk = 0x80;
    load = 0;       // pull down load/cs to begin communication.
    sck = 0;        // pull down CLOCK to prepare for communication.
    for (i=0; i<8; i++){
        sck = 0;    // pull down to prepare data.
        _nop_();     // delay will be needed on Dallas MCUs.
        d_out = (((addr&comm_msk)==0)?0:1);
        sck = 1;    // pull up to send one bit.
        comm_msk >>= 1;
    }
    comm_msk = 0x80;
    for (i=0; i<8; i++){
        sck = 0;    // pull down to prepare data.
        _nop_();     // delay will be needed on Dallas MCUs.
        d_out = (((val&comm_msk)==0)?0:1);
        sck = 1;    // pull up to send one bit.
        comm_msk >>= 1;
    }
    load = 1;
}
/**
 * led_init will configure the MAX7219 to a proper state:
 *     dig.1~dig.4 decode B mode
 *     scanning from dig.1 to dig.4
 *     intensity set to 1/2.
 *     blank display for dig.1 to dig.3
 *     0 display for dig.4 (most right)
 */
void led_init(){
    send_word(0x0c, 0x00);  // stop display.
    //send_word(0x09, 0xff);  // write to decode mode, setting to mode B
    send_word(0x0b, 0x03);  // scan dig.1 to dig.4
    send_word(0x0a, 0x0a);  // set intensity to 21/32
    /*
    // set dig.1 to dig.3 to BLANK.
    send_word(0x01, 0x7f);
    send_word(0x02, 0x7f);
    send_word(0x03, 0x7f);
    // set dig.4 to 0
    send_word(0x04, 0x80);
    */
    send_word(0x0c, 0x01);  // start display.
}
/**
 * showing copyright string on the numeric LEDs: JUdE
 */
void show_copyright(){
    send_word(0x09, 0x00);  // disable decoding.
    send_word(0x01, 0x38);  // lighting B.C.D for J
    send_word(0x02, 0x3e);  // lighting B.C.D.E.F for U
    send_word(0x03, 0x30);  // lighting B.C.D.E.G for d
    send_word(0x04, 0xcf);  // lighting A.D.E.F.G and DP for E.
    send_word(0x09, 0xff);  // enable decoding.
}
/**
 * showing a float value on the numeric LEDs
 * CAUTION: used only for FOUR digs.
 * redesign is required for LCD display.
 */
    #define CLEAN {send_word(0x01,0x7f);\
        send_word(0x01,0x7f);\
        send_word(0x01,0x7f);\
        send_word(0x01,0x7f);}
    #define SHOW_ERROR send_word(0x01, 0x0b)   // show E on left.
void show_float(float val){
    char dp_shift = 0;
    long int val_int = 0;
    int tmp = 0;
    char i;
    byte digs[4];
    bit minus_sign = 0;
    bit pre_zero_flag = 0;
    if (val >= 10000){      // overflow the whole 4 digs.
        CLEAN;
        SHOW_ERROR;
    }
    while (val < 100){      // smaller than unified region.
        val *=10;
        dp_shift ++;
    }
    while (val >= 1000){    // larger than unified region.
        val /=10;
        dp_shift --;
    }
    // round the last digit.
    val_int = (long int)(val*100);
    tmp = val_int - (val_int/10)*10;
    val_int = (val_int/10)*10;
    if (tmp>=5)
        val_int += 10;
    val = val_int /100.0;
    // get every digits.
    minus_sign = (val<0)?1:0;
    for (i=3; i>=0; i--){
        digs[i] = (byte)((val-(int)val)*10);
        val /= 10;
    }
    // set the decimal point
    digs[2-dp_shift] |= 0x80;
    // show every dig here.
    for (i=0; i<4; i++){
        if (digs[i] != 0){
            send_word(i+1, digs[i]);
            pre_zero_flag = 1;
        } else {
            if (pre_zero_flag != 0){
                send_word(i+1, 0x00);
            }
        }
    }
    if (minus_sign == 1)
        sign_led = 0;
}
/**
 * show_digs will display the whole current_digs array to the LEDs
 */
void show_digs(){
    byte i;
    for (i=0; i<4; i++){
        send_word(i+1, current_digs[i]);
    }
}
/**
 * flow_control function
 */
byte flow_control(byte key_value){
    static float last_val = 0;      // The last operant.
    static byte last_op = 0;        // The last operator.
    static bit lock = 0;            // Flag for locking.
    static byte current_index = 0;
    static byte dot_flag = 0;
    // The state value to return.
    byte result = STATE_IDLE;
    static float value = 0;
    float _key_value = 0;
    int i = 0;

    
    if (key_value<10){
        // a digit has been inputed.
        if (lock != 0)  return result;
        if (current_index<DATA_WIDTH){
            if (dot_flag != 0){
                _key_value = key_value;
                for (i=0; i<dot_flag; i++) _key_value /= 10;
                value += _key_value;
            } else {
                value *= 10; value += key_value;
            }
            result = STATE_NUM;
        }
    } else if (key_value == '.'){
        if (dot_flag == 0){
            dot_flag = 1;
            result = STATE_DOT;
        } else
            result = STATE_IDLE;
    } else {
        // a special key has been inputted.
        result = STATE_REFRESH;
        switch (key_value){
            case 's':   // do operation on the current value.
                value = sqrt(value);
                calc_res = value;
                lock = 1;
                break;
            default:    // do operation with the last value.
                switch (last_op) {
                    case 0:
                        last_val = value;
                        calc_res = last_val;
                        break;
                    case '+':
                        calc_res = last_val + value;
                        break;
                    case '-':
                        calc_res = last_val - value;
                        break;
                    case '*':
                        calc_res = last_val * value;
                        break;
                    case '/':
                        if (value == 0)
                            // divide by zero error.
                            result = STATE_ERROR;
                        else
                            calc_res = last_val / value;
                        break;
                }
                value = 0;
                lock = 0;
                last_val = calc_res;
                last_op = key_value;
                break;
        }
        dot_flag = 0;
    }
    return result;
}

void tests(){
	byte tmp;
    shift_flag = 0;
    led_init();
    show_copyright();

    /* // debug flow_control
    tmp = flow_control(1);
    tmp = flow_control('.');
    tmp = flow_control('+');
    tmp = flow_control(2);
    tmp = flow_control(5);
    tmp = flow_control('s');
    tmp = flow_control('=');
    _nop_();
    */

    /* // test sqrt
    show_float(sqrt(25));
    */

    /* // test show_float
    show_float(12.345);     // should be 123.5
    show_float(12.3);       // should be 12.3
    */

    /* // test keyboard driver
    while(1){
		tmp = kb_scan();
		send_word(0x04,tmp);
	}
    */
}

void main(){
    byte theKey, state;
    byte i;
    bit refresh_flag = 0;
    // initializing...
    shift_flag = 0;
    shift_led = 1;
    sign_led = 1;
    led_init();
    show_copyright();
    // end of initialization.
    theKey = kb_scan();
    CLEAN;
    while (1){
        state = flow_control(theKey);
        switch (state){
        case STATE_NUM:
            if (refresh_flag == 1){
                for (i=0; i<4; i++) current_digs[i]=0x7f;
                refresh_flag = 0;
            }else{
                for (i=1; i<4; i++) current_digs[i-1]=current_digs[i];
            }
            current_digs[3] = theKey;
            show_digs();
            break;
        case STATE_DOT:
            current_digs[3] |= 0x80;
            send_word(4, current_digs[3]);
            break;
        case STATE_REFRESH:
            refresh_flag = 1;
            show_float(calc_res);
            break;
        case STATE_ERROR:
            for (i=0; i<4; i++) current_digs[i]=0x7f;
            current_digs[0] = 0x0b;
            show_digs();
            break;
        case STATE_IDLE:
            break;
        case STATE_SIGN:
            sign_led = ~sign_led;
            break;
        }
        theKey = kb_scan();
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -