沒事做了一個電子秤仿真
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
電子秤.PNG (58.74 KB, 下載次數: 120)
下載附件
2017-6-8 16:34 上傳
單片機代碼:
- #include<reg52.h>
- #include<intrins.h>
- #include"delay.h"
- #define uchar unsigned char
- #define uint unsigned int
- #define WRITE_ADDR 0x90
- #define AD_COMMAND 0x00
- #define READ_ADDR 0x91
- /*管腳定義*/
- sbit SDA = P2^0;
- sbit SCL = P2^1;
- sbit shumaguan1 = P3^4;
- sbit shumaguan2 = P3^5;
- sbit shumaguan3 = P3^6;
- sbit shumaguan4 = P3^7;
- sbit xiaoshudian = P0^7;
- sbit alarm = P2^2;
- /*共陰極數碼管編碼*/
- uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
- /*全局變量*/
- uchar adc_data = 0; //記錄每一次讀取的adc數據
- uchar key_value =0; //記錄每一次按鍵值
- uchar temp_data[4] = {0}; //記錄輸入的單價
- uchar point_place = 0; //記錄小數點位置
- uchar wei_shu = 0; //記錄總共數據位數
- uchar equal_sign = 0; //記錄是否按下“=”號
- uchar interrupt_flag = 0; //發生中斷標記
- uint price = 0; //用來記錄單價
- /*微秒級別延時(5us)*/
- void delay_us()
- {;;}
- /*毫秒級別延時(z微妙)*/
- void delay_ms(unsigned int z)
- {
- unsigned int x,y;
- for(x = z;x > 0;x--)
- for(y = 120 ;y>0;y--);
- }
- /*報警*/
- void beep_on(void)
- {
- alarm = 0;
- }
- void beep_off(void)
- {
- alarm = 1;
- }
- /*鍵盤讀取函數*/
- uchar keyboard_read()
- {
- uchar key,temp;
- P1=0xfe;
- temp=P1;
- temp=temp&0xf0;
- if(temp!=0xf0)
- {
- delay_ms(10);
- if(temp!=0xf0)
- {
- temp=P1;
- switch(temp)
- {
- case 0xee:
- key=7;
- break;
- case 0xde:
- key=8;
- break;
- case 0xbe:
- key=9;
- break;
- case 0x7e:
- key='/';
- break;
- }
- while(temp!=0xf0)
- {
- temp=P1;
- temp=temp&0xf0;
- }
- }
- }
- P1=0xfd;
- temp=P1;
- temp=temp&0xf0;
- if(temp!=0xf0)
- {
- delay_ms(10);
- if(temp!=0xf0)
- {
- temp=P1;
- switch(temp)
- {
- case 0xed:
- key=4;
- break;
- case 0xdd:
- key=5;
- break;
- case 0xbd:
- key=6;
- break;
- case 0x7d:
- key='*';
- break;
- }
- while(temp!=0xf0)
- {
- temp=P1;
- temp=temp&0xf0;
- }
- }
- }
- P1=0xfb;
- temp=P1;
- temp=temp&0xf0;
- if(temp!=0xf0)
- {
- delay_ms(10);
- if(temp!=0xf0)
- {
- temp=P1;
- switch(temp)
- {
- case 0xeb:
- key=1;
- break;
- case 0xdb:
- key=2;
- break;
- case 0xbb:
- key=3;
- break;
- case 0x7b:
- key='-';
- break;
- }
- while(temp!=0xf0)
- {
- temp=P1;
- temp=temp&0xf0;
- }
- }
- }
- P1=0xf7;
- temp=P1;
- temp=temp&0xf0;
- if(temp!=0xf0)
- {
- delay_ms(10);
- if(temp!=0xf0)
- {
- temp=P1;
- switch(temp)
- {
- case 0xe7:
- key='.';
- break;
- case 0xd7:
- key=0;
- break;
- case 0xb7:
- key='=';
- break;
- case 0x77:
- key='+';
- break;
- }
- while(temp!=0xf0)
- {
- temp=P1;
- temp=temp&0xf0;
- }
- }
- }
- return key;
- }
- /*iic開始信號*/
- void start()
- {
- SCL = 1;
- _nop_();
- SDA = 1;
- delay_us();
- SDA = 0;
- delay_us();
- SCL = 0;//拉低時鐘線,開始信號以后方便更改SDA 上面的數據來發送
- _nop_();
- }
- /*iic 停止信號*/
- void stop()
- {
- SCL = 1;
- _nop_();
- SDA = 0;
- delay_us();
- SDA = 1;
- delay_us();
- }
- /*回復響應信號*/
- void respond()
- {
- SCL = 1;
- _nop_();
- SDA = 0;
- delay_us();
-
- SCL = 0; //凡是在一個小節后拉低SCL 都是為了方便接下來的 數據傳輸
- _nop_();
- }
- /*不響應*/
- void norespond()
- {
- SCL = 1;
- _nop_();
- SDA = 1;
- delay_us();
- }
- /*初始化iic總線*/
- void init_iic_line()
- {
- SCL = 1;
- _nop_();
- SDA = 1;
- _nop_();
- }
- /*往iic設備發送數據,先發送數據的最高位 */
- void write_byte(uchar value)
- {
- uchar i,temp;
- temp = value;
- for(i = 0;i<8;i++)
- {
- SCL = 0;
- _nop_();
- if((temp & 0x80) == 0x80)
- {
- SDA = 1;
- }
- else
- {
- SDA = 0;
- }
- SCL = 1;
- _nop_();
- temp <<=1;
- }
- SCL = 0;
- _nop_();
- }
- /*讀取iic設備發送過來的數據*/
- uchar read_byte()
- {
- uchar i, return_value = 0;
- SDA = 1;//釋放數據線,交給從機控制
- _nop_();
- SCL = 0;
- _nop_();
- for(i = 0;i<8;i++)
- {
- SCL = 1;
- if(SDA == 1)
- {
- return_value = return_value |0x01;
- }
- if(i<7)//這里很重要
- {
- return_value <<= 1;
- }
- SCL = 0;
- _nop_();
- }
- return return_value;
- }
- /*顯示一個數碼管*/
- void display_one(uchar value)
- {
- P0 = table[value];
- }
- /*初始化iic設備*/
- void init_iic_device()
- {
- start();
- write_byte(WRITE_ADDR);
- respond();
- write_byte(AD_COMMAND);
- respond();
- }
- /*讀取adc數據*/
- uchar read_adc_data()
- {
- uchar adc_data = 0;
- start();
- write_byte(READ_ADDR);
- respond();
- adc_data = read_byte();
- norespond();
- stop();
- return adc_data;
- }
- /*adc數據處理*/
- void adc_data_process()
- {
- long temp_weight;
- temp_weight = ((long)adc_data)*1000/51;
- temp_data[0] = temp_weight/1000;
- temp_data[1] = temp_weight%1000/100;
- temp_data[2] = temp_weight%1000%100/10;
- temp_data[3] = temp_weight%1000%100%10;
- point_place = 1;
- wei_shu = 4;
- }
- /*選擇哪個數碼管亮*/
- void shumaguan_slect_on(uchar num)
- {
- uchar temp = 4;
- temp = temp-(wei_shu -num);
- switch(temp)
- {
- case 0:
- shumaguan1 = 0;
- break;
- case 1:
- shumaguan2 = 0;
- break;
- case 2:
- shumaguan3 = 0;
- break;
- case 3:
- shumaguan4 = 0;
- break;
- default:
- break;
- }
- }
- /*選擇哪個數碼管熄滅*/
- void shumaguan_slect_off(uchar num)
- {
- uchar temp = 4;
- temp = temp-(wei_shu -num);
- switch(temp)
- {
- case 0:
- shumaguan1 = 1;
- break;
- case 1:
- shumaguan2 = 1;
- break;
- case 2:
- shumaguan3 = 1;
- break;
- case 3:
- shumaguan4 = 1;
- break;
- default:
- break;
- }
- }
- void clear_led(void)
- {
- shumaguan1 = 1;
- shumaguan2 = 1;
- shumaguan3 = 1;
- shumaguan3 = 1;
- }
- /*顯示子程序,支持顯示重量,單價,總價*/
- void display()
- {
- uchar i;
- clear_led();
- for(i = 0;i < wei_shu;i++)
- {
- if((i + 1) == point_place)
- {
- shumaguan_slect_off(i);
- display_one(temp_data[i]);
- xiaoshudian = 1;
- shumaguan_slect_on(i);
- delay_ms(5);
- shumaguan_slect_off(i);
- }
- else
- {
- shumaguan_slect_off(i);
- display_one(temp_data[i]);
- shumaguan_slect_on(i);
- delay_ms(5);
- shumaguan_slect_off(i);
- }
- }
- }
- /*計算總價并將總價每一位分離*/
- void calculate_total_price()
- {
- int temp_number = 0 ;
- unsigned long total_price = 0;
- switch(wei_shu -point_place)
- {
- case 3:
- temp_number = 100;
- break;
- case 2:
- temp_number = 10;
- break;
- case 1:
- temp_number = 1;
- break;
- }
- total_price = (unsigned long)price * (unsigned long)adc_data*1000;
- total_price = total_price/51/temp_number/1000;
- if(total_price <10000&&total_price>999)
- {
- temp_data[0] = total_price/1000;
- temp_data[1] = total_price%1000/100;
- temp_data[2] = total_price%1000%100/10;
- temp_data[3] = total_price%1000%100%10;
- wei_shu = 4;
- point_place = 3;
- }
- else if(total_price <1000&&total_price >99)
- {
- temp_data[0] = total_price/100;
- temp_data[1] = total_price%100/10;
- temp_data[2] = total_price%100%10;
- wei_shu = 3;
- point_place = 2;
- }
- else if(total_price < 100&&total_price>9)
- {
- temp_data[0] = total_price/10;
- temp_data[1] = total_price%10;
- wei_shu = 2;
- point_place = 1;
- }
- else
- {
- temp_data[0] = total_price/10;
- temp_data[1] = total_price%10;
- wei_shu = 2;
- point_place = 1;
- }
- }
- /*中斷初始化*/
- void interrupt_init()
- {
- EA = 1; //開總中斷
- IT0 = 0; //設置外部中斷0為下降沿觸發
- EX0 = 1; //開外部中斷0
- P1 = 0xf0; //初始化矩陣鍵盤外部引腳電平
- }
- int main()
- {
- interrupt_init();
- init_iic_line();
- init_iic_device();
- /*讀取傳感器并顯示重量,直到鍵盤輸入重量跳出*/
- while(1)
- {
- if(interrupt_flag != 1)
- {
- adc_data = read_adc_data();
- adc_data_process();
- display();
- }
- else
- {
- clear_led();
- break;
- }
- }
- /*顯示從鍵盤輸入的單價*/
- while(1)
- {
- if(equal_sign != 1)
- {
- display();
- adc_data = read_adc_data();
- if(adc_data == 0)
- {
- break;
- }
- }
- else
- {
- break;
- }
- }
- /*計算總價并顯示,直到重量為0 ,表示稱量物品已經離開,回到程序開始執行處*/
- calculate_total_price();
- while(1)
- {
- adc_data = read_adc_data();
- if(adc_data != 0)
- {
- display();
- }
- else
- {
- uchar i = 0;
- for(i = 0 ; i<4 ; i++)
- {
- temp_data[i] = 0;
- }
- adc_data = 0;
- key_value = 0;
- point_place = 0;
- wei_shu = 0;
- equal_sign = 0;
- interrupt_flag = 0;
- price = 0;
- break;
- }
- }
- return 0;
- }
- /***************************中斷處理函數************************/
- void keyboard_int(void) interrupt 0
- {
- EA = 0;
- /*清除數據 */
- if(interrupt_flag == 0)
- {
- wei_shu = 0;
- point_place = 0;
- }
- /*讀取鍵盤值*/
- key_value = keyboard_read();
- if(key_value != '=')
- {
- if(wei_shu <4)
- {
- if(key_value!='.')
- {
- temp_data[wei_shu] = key_value;//將價格存入數組temp_data中
- wei_shu ++;
- price = price *10 + key_value;
- }
- else
- {
- point_place = wei_shu; //記錄小數點位置
- }
- }
- }
- else
- {
- equal_sign = 1;
- }
- interrupt_flag = 1;
- P1 = 0xf0;
- EA = 1;
- }
復制代碼
|