📄 test.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 + -