我的程序功能是在数码管显示计数的同时,在外部中断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高级中断,符合设计要求
}
}
C:\Users\admin\Desktop |