我的单片机程序功能是在数码管显示计数的同时,在外部中断0的端口加了一个按键,当按键按下时,实行外部中断函数,数码管显示光敏电阻电压值。
遇到问题:当按键按下时,数码管不变化,没有显示电压值。
仿真图+程序见下图:
- #include<reg51.h>
- #include<absacc.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- /*********************************端口定义**********************************/
- sbit CS = P3^5;
- sbit Clk = P3^4;
- sbit DATI = P3^3;
- sbit DATO = P3^3;
- sbit KEY1 = P3^2;
- /*******************************定义全局变量********************************/
- unsigned char dat = 0x00; //AD值 .
- //若dat=adc0832(CH)*500.0/255; 不可用unsigned char dat
- //500不可以。用500.0
- //如 下面unsigned int disdat; 不可unsigned char disdat
- unsigned char CH; //通道变量
- unsigned int dis[] = {0x00, 0x00, 0x00}; //显示数值
- uchar code dispcode[ ]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00}; /*七段共阴管显示定义*/
- char code tablewe[]={ 0xfe,0xfd,0xfb,0xf7,0xef,0xdf}; /*七段共阴管位选显示定义*/
- uchar seconde=0; /*定义并初始化变量*/
- uchar minite=0;
- uchar hour=0;
- uchar a=0;
- uint mstcnt=0;
- /*函数声明*/
- void delay(uchar k ); //延时子程序
- void time_pro( ); //时间处理子程序
- void display( ); //显示子程序
- void led_display( ); //led闪烁程序
- void convdata( ) ; //电压计算数据程序
- void display_key1(void); //数码管显示数据程序,中断进行
- /*****************************************/
- /*************AD转换子程序****************/
- /*****************************************/
- unsigned char adc0832(unsigned char CH)
- {
- unsigned char i,test,adval;
- adval = 0x00;
- test = 0x00;
- Clk = 0; //初始化
- CS=1;
- DATI = 1;
- CS = 0;
- _nop_();
- Clk = 1;
- _nop_();
- if ( CH == 0x00 ) //通道选择
- {
- Clk = 0; //写入10,选单极性0通道
- DATI = 1; //通道0的第一位
- _nop_(); //clk上升沿写进去
- Clk = 1;
- _nop_();
- Clk = 0;
- DATI = 0; //通道0的第二位
- _nop_();
- Clk = 1;
- _nop_();
- }
- else
- { //写入11,选单极性1通道
- Clk = 0;
- DATI = 1; //通道1的第一位
- _nop_(); //clk上升沿写进去
- Clk = 1;
- _nop_();
- Clk = 0;
- DATI = 1; //通道1的第二位
- _nop_();
- Clk = 1;
- _nop_();
- }
- Clk = 0; //写进空闲位 //clk上升沿写进去
- DATI = 1;
- _nop_();
- Clk = 1;
- _nop_();
- //读取前8位的值
- for( i = 0;i < 8;i++ ) //读取前8位的值
- { //clk下升沿读出来
- _nop_(); //高位先行
- adval <<= 1;
- Clk = 1;
- _nop_();
- Clk = 0;
- if (DATO)
- adval |= 0x01;
- //else
- // adval |= 0x00;
- }
- for (i = 0; i < 8; i++) //读取后8位的值
- { //clk下升沿读出来
- test >>= 1; //低位先行,时序图上
- if (DATO)
- test |= 0x80;
- //else
- //test |= 0x00;
- _nop_();
- Clk = 1;
- _nop_();
- Clk = 0;
- }
- if (adval == test) //比较前8位与后8位的值,如果不相同舍去。
- dat = adval; //若一直出现显示为零,请将该行去掉
- _nop_();
- CS = 1; //释放ADC0832,关闭
- DATO = 1;
- Clk = 1;
- return dat;
- }
- /**************************************************/
- /*****将0-255级换算成0.00-5.00的电压数值***********/
- /**************************************************/
- void convdata(unsigned char i) //i=dat*5/255=51,是255份; 256份误差大
- {
- unsigned int disdat; //不可unsigned char disdat
- disdat=i*500.0/255; //500不可以。用500.0
- /* 验证读数
- dis[0] = i/100; //个位
- dis[1] = i/10%10; //小数点后第一位
- dis[2] = i%10; //小数点后第二位 */
-
- dis[0] = disdat/100; //个位
- dis[1] = disdat/10%10; //小数点后第一位
- dis[2] = disdat%10; //小数点后第二位
- }
- /*****************************************/
- /*****数码管显示光敏电阻电压程序**********/
- /*****************************************/
- void display_key1(void)
- {
- P1=0xfe;
- P0= dispcode[dis[0]] + 0x80; //显示个位和小数点
- delay(5);
- P1=0xfd;
- P0=dispcode[dis[1]]; //显示小数点后第一位
- delay(5);
- P1=0xfb;
- P0=dispcode[dis[2]]; //显示小数点后第二位
- delay(5);
- }
- /*****************************/
- /*led灯闪烁程序*/
- /****************************/
- void led_display(void)
- {
- delay(50); //led灯闪烁三次后熄灭
- P2=0x07; //赋初始值
- delay(50);
- P2=0x00;
- delay(50);
- P2=0x07;
- delay(50);
- P2=0x00;
- delay(50);
- P2=0x07;
- delay(50);
- P2=0x00;
- }
- /*****************************/
- /*延时子程序*/
- /****************************/
- void delay (uchar k)
- {
- uchar j;
- while((k--)!=0)
- {
- for(j=0;j<125;j++)
- {;}
- }
- }
- /**************************/
- /*时间处理子程序*/
- /**************************/
- void time_pro( void)
- {
- if(seconde==60) //秒钟设为60进制
- {
- seconde=0;
- minite++;
- if(minite==60) //分钟设为60进制
- {
- minite=0;
- hour++;
- if(hour==24) //时钟设为24进制
- {
- hour=0;
- }
- }
- }
- }
- /*****************************/
- /* 显示子程序*/
- /*****************************/
- void display()
- {
- static uchar i=0;
- P0=0x00; //消隐
- switch(i)
- {
- case 0: P1=0xfe;
- P0=dispcode[hour/10];//显示小时的十位
- i++;
- break;
- case 1: P1=0xfd;
- P0=(dispcode[(hour%10)])|0X80;//显示小时的个位
- i++;
- break;
- case 2: P1=0xfb;
- P0=dispcode[minite/10];//显示分的十位
- i++;
- break;
- case 3: P1=0xf7;
- P0=(dispcode[minite%10])|0X80;//显示分的个位
- i++;
- break;
- case 4: P1=0xef;
- P0=dispcode[seconde/10];//显示秒的十位
- i++;
- break;
- case 5: P1=0xdf;
- P0=dispcode[seconde%10];//显示秒的个位
- i=0;
- break;
- }
- }
- /**************************/
- /*主函数*/
- /**************************/
- void main(void)
- {
- P1=0xff; //初始化p1口,全设为1
- TMOD=0x01; //time0为定时器,方式1
- TH0=0xfc; //预置计数初值1ms
- TL0=0x18;
- EA=1;
- ET0=1;
- TR0=1;
- while (1)
- {
- if(a==0)
- {
- led_display( ); //led灯闪烁
- time_pro( ); //时间处理
- }
- else
- display_key1();
- }
- }
- /*****两个中断程序,一个计数器T0中断,一个外部INT0中断*****/
- /**********************************************************/
- /* 中断服务程序实现数码管的定时显示 计数器中断 */
- /**********************************************************/
- void timer0(void) interrupt 1 using 0 //定时器0方式1,16位计数器,50ms中断一次
- {
- PT0=0; //设置为低级中断
- TH0=0xfc; //重置计数初值1ms
- TL0=0x18;
- mstcnt++;
- if(mstcnt>=1000)
- {
- seconde++;
- mstcnt=0;
- }
- display( ); //显示时间T1高级中断
- a=0;
- }
- /**********************************************************/
- /* 外部中断————实现按键按下时电压显示 */
- /**********************************************************/
- void int0(void) interrupt 0
- {
- PX0=1; //设置为高级中断
- CH = 0x00; //在这里选择通道 0x00(单极性0通道)或0x01(单极性1通道)
- if (KEY1 == 0)
- {
- a++;
- P1=0x00; //端口初始化
- P0=0xff;
- dat = adc0832(CH);
- convdata(dat); //数据转换
- // display_key1(); //显示数值INT0高级中断,符合设计要求
- }
- }
复制代码
|