没事做了一个电子秤仿真
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机代码:
- #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;
- }
复制代码
|