标题:
51单片机采样频率可调的幅值采集,显示,传输
[打印本页]
作者:
qwer32855
时间:
2018-7-9 09:04
标题:
51单片机采样频率可调的幅值采集,显示,传输
#include <reg52.h>
#include <intrins.h>
bit flag =1; //采样刷新标志位
sbit SCL = P2^1; //I2C时钟
sbit SDA = P2^0; //I2C数据
sbit du=P2^6; //数码管段选
sbit we=P2^7; //数码管位选
sbit RST=P2^4; //DS1302时钟使能端
sbit in1=P3^4; //键盘行扫描检测
sbit in2=P3^5;
sbit in3=P3^6;
sbit in4=P3^7;
sbit bibi=P2^3;
unsigned int code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //数码管显示译码
unsigned int buffer[3]={0x00,0x00,0x00}; //电压显示缓存
unsigned char Ratebuffer[6]; //采样周期送串口缓存
unsigned int ConfigBuffer[4]; //采样周期数码管显示缓存
unsigned char sending; //串口发送一字节数据发送完成标志位
unsigned int Timerflag=1000; //采样周期全局变量
unsigned int TimerflagBuffer; //采样周期缓存,用于判断采样周期是否发生变化,若是则送24C02储存
unsigned char TimerT0[4]; //存储按键设置的采样周期各位数
unsigned char num1; //将采样周期分解为两个8位数据,送24C02存储
unsigned char num2;
unsigned int te;
unsigned int tr;
unsigned int valu;
void Delay(); //用于I2C总线延迟
void delay1(unsigned char a); //用于数码管显示延迟以及24C02存储延迟
void Start(); //I2C总线开始信号
void Stop(); //I2C总线结束信号
bit Write(unsigned char dat); //向I2C总线写一字节数据,并返回应答信号
unsigned char ReadNAK(); //从I2C总线读一字节数据
unsigned char ReadACK(); //从I2C总线读多字节数据
void Timer(); //1ms定时,用于采样周期
unsigned char ADC(unsigned char ch); //从ADC读一字节数据
void display(unsigned int t0,unsigned int t1,unsigned int t2); //数码管显示电压值
void display2(unsigned int t0,unsigned int t1,unsigned int t2,unsigned int t3); //数码管显示采样周期
void transfer(unsigned char *str,unsigned int val); //将电压值转换为ASCII码,用于串口发送
void UART(); //设置串行通信
void Config(); //设置外部中断1
unsigned char E2Read(unsigned char addr); //从24C02读取最后一次设置的采样周期,用于程序初始化
void E2Write(unsigned char addr,unsigned char dat); //向24C02写入变化后的采样周期
void main()
{
unsigned int val;
unsigned char str[10];
unsigned char i;
RST=0; //DS1302芯片占用I2C总线,应先关闭使能
num1=E2Read(0);
num2=E2Read(1);
Timerflag=num2*256+num1;
TimerflagBuffer=Timerflag;
Config();
Timer();
UART();
while(1)
{
if(in1==0) //若按键1按下,则进入外部中断1
P3=0xf7;
if(flag==1)
{
flag=0;
val=ADC(2);
val=196*val/100; //转换ADC读出的原始数据,避免小数运算
valu=val;
buffer[0]=table[val%10];
buffer[1]=table[val/10%10];
buffer[2]=table[val/100%10]+0x80;
Ratebuffer[0]=','; //将采样周期转ASCII码,用于串口发送
Ratebuffer[1]=Timerflag/1000%10+'0';
Ratebuffer[2]=Timerflag/100%10+'0';
Ratebuffer[3]=Timerflag/10%10+'0';
Ratebuffer[4]=Timerflag%10+'0';
Ratebuffer[5]=',';
transfer(str,val);
for(i=0;i<5;i++)
{
SBUF=str[i];
sending=1;
while(sending);
}
for(i=0;i<6;i++)
{
SBUF=Ratebuffer[i];
sending=1;
while(sending);
}
}
display(buffer[0],buffer[1],buffer[2]);
if(valu>400)
{
if(te<200)bibi=0;
else bibi=1;
}
if(valu<150)
{
if(tr<800)bibi=0;
else bibi=1;
}
if(valu>150&&valu<400)
{
te=0;
tr=0;
bibi=1;
}
if(TimerflagBuffer!=Timerflag) //检测采样周期变化,并存储到掉电不丢失模块
{
num2=Timerflag/256;
num1=Timerflag%256;
E2Write(0,num1);
E2Write(1,num2);
TimerflagBuffer=Timerflag;
}
}
}
void Delay()
{
_nop_();_nop_();_nop_();_nop_();
}
void delay1(unsigned char a)
{
unsigned char j,k;
for(j=a;j>0;j--)
for(k=125;k>0;k--);
}
void Start()
{
SDA=1;
SCL=1;
Delay();
SDA=0;
Delay();
SCL=0;
}
void Stop()
{
SCL=0;
SDA=0;
Delay();
SCL=1;
Delay();
SDA=1;
Delay();
}
bit Write(unsigned char dat)
{
bit ack;
unsigned char mask;
for(mask=0x80;mask!=0;mask>>=1)
{
if((mask&dat)==0)
{
SDA=0;
}
else
{
SDA=1;
}
Delay();
SCL=1;
Delay();
SCL=0;
}
SDA=1;
Delay();
SCL=1;
ack=SDA;
Delay();
SCL=0;
return(ack);
}
unsigned char ReadNAK()
{
unsigned char mask;
unsigned char dat;
SDA=1;
for(mask=0x80;mask!=0;mask>>=1)
{
Delay();
SCL=1;
if(SDA==0)
{
dat&= ~mask;
}
else
{
dat|=mask;
}
Delay();
SCL=0;
}
SDA=1;
Delay();
SCL=1;
Delay();
SCL=0;
return dat;
}
unsigned char ReadACK()
{
unsigned char mask;
unsigned char dat;
SDA=1;
for(mask=0x80;mask!=0;mask>>=1)
{
Delay();
SCL=1;
if(SDA==0)
{
dat&=~mask;
}
else
{
dat|=mask;
}
Delay();
SCL=0;
}
SDA=0;
Delay();
SCL=1;
Delay();
SCL=0;
return(dat);
}
void Timer()
{
TMOD=0x01;
TH0=0xfc;
TL0=0x66;
ET0=1;
EA=1;
TR0=1;
}
unsigned char ADC(unsigned char ch)
{
unsigned char val;
EA=0;
Start();
if(Write(0x48<<1))
{
Stop();
return 0;
}
Write(0x40|ch);
Start();
Write((0x48<<1)|0x01);
val=ReadACK();
val=ReadNAK();
Stop();
EA=1;
return val;
}
void display(unsigned int t0,unsigned int t1,unsigned int t2)
{
P0=t0;du=1;du=0;P0=0xdf;we=1;we=0;delay1(5);
P0=t1;du=1;du=0;P0=0xef;we=1;we=0;delay1(5);
P0=t2;du=1;du=0;P0=0xf7;we=1;we=0;delay1(5);
}
void display2(unsigned int t0,unsigned int t1,unsigned int t2,unsigned int t3)
{
P0=t0;du=1;du=0;P0=0xdf;we=1;we=0;delay1(5);
P0=t1;du=1;du=0;P0=0xef;we=1;we=0;delay1(5);
P0=t2;du=1;du=0;P0=0xf7;we=1;we=0;delay1(5);
P0=t3;du=1;du=0;P0=0xfb;we=1;we=0;delay1(5);
}
void transfer(unsigned char *str,unsigned int val)
{
str[0]=(val/100%10)+'0';
str[1]='.';
str[2]=(val/10%10)+'0';
str[3]=(val%10)+'0';
str[4]='V';
}
void UART()
{
EA=0;
SCON=0x50;
PCON=0x00;
TMOD|=0x20;
TH1=0xfd;
TL1=0xfd;
REN=1;
ES=1;
TR1=1;
EA=1;
}
void Config()
{
EA=0;
TCON|=0x04;
P3=0xff;
EX1=1;
EA=1;
}
unsigned char E2Read(unsigned char addr)
{
unsigned char dat;
Start();
Write(0xa0);
Write(addr);
Start();
Write(0xa1);
dat=ReadNAK();
Stop();
delay1(100);
return dat;
}
void E2Write(unsigned char addr,unsigned char dat)
{
Start();
Write(0xa0);
Write(addr);
Write(dat);
Stop();
delay1(5000);
}
void interruptT0() interrupt 1 //定时器T0中断,通过标志位完成设置的采样周期计时
{
static unsigned long t = 0;
TH0=0xfc;
TL0=0x66;
t++;
if(valu>400)
{
te++;
if(te>400)
te=1;
}
if(valu<400&&valu>150)
{
te=0;tr=0;bibi=1;
}
if(valu<150)
{
tr++;
if(tr>1600)
tr=1;
}
if(t>=Timerflag)
{
t=0;
flag=1;
}
}
void interruptS() interrupt 4
{
unsigned long temp;
static signed char n=3;
static unsigned char t[4]; //串口接收到的采样周期缓存
if(RI==1)
{
EA=0;
RI=0;
temp=SBUF;
if(n>=0)
{
t[n]=temp-'0'; //将接收到的ASCII码转换为10进制存储
n--;
}
if(n<0) //接收到四位数后更新采样周期
{
n=3;
Timerflag=t[3]*1000+t[2]*100+t[1]*10+t[0];
}
EA=1;
}
else
{
TI=0;
sending=0;
}
}
void interruptEX0() interrupt 2 //外部中断1,完成按键操作,进入中断后立即显示当前的采样周期
{
signed char i;
bit backup; //按键备份,用于去抖
REN=0;
EA=0;
ConfigBuffer[0]=table[Timerflag%10];
ConfigBuffer[1]=table[Timerflag/10%10];
ConfigBuffer[2]=table[Timerflag/100%10];
ConfigBuffer[3]=table[Timerflag/1000%10];
while(1)
{
display2(ConfigBuffer[0],ConfigBuffer[1],ConfigBuffer[2],ConfigBuffer[3]);
if(in2==0) //按键2按下则退出中断服务程序
{
P3=0xff;
EA=1;
break;
}
if(in3==0) //按键3按下则开始设置采样周期,并在数码管显示
{
while(in3!=1); //检测按键跳变
ConfigBuffer[0]=0x00;ConfigBuffer[1]=0x00;ConfigBuffer[2]=0x00;ConfigBuffer[3]=0x00;
while(1)
{
for(i=3;i>=0;i--) //键盘矩阵扫描,读取4位采样周期
{
while(1)
{
display2(ConfigBuffer[0],ConfigBuffer[1],ConfigBuffer[2],ConfigBuffer[3]);
P3=0xfe;
if(in1==0)
{
backup=in1; //按键去抖
delay1(20);
if(backup!=in1)continue;
while(in1!=1); //检测跳变为一次有效按键
ConfigBuffer[i]=table[0];TimerT0[i]=0;break;
}
if(in2==0)
{
backup=in2;
delay1(20);
if(backup!=in2)continue;
while(in2!=1);
ConfigBuffer[i]=table[1];TimerT0[i]=1;break;
}
if(in3==0)
{
backup=in3;
delay1(20);
if(backup!=in3)continue;
while(in3!=1);
ConfigBuffer[i]=table[2];TimerT0[i]=2;break;
}
if(in4==0)
{
backup=in4;
delay1(20);
if(backup!=in4)continue;
while(in4!=1);
ConfigBuffer[i]=table[3];TimerT0[i]=3;break;
}
P3=0xfd;
if(in1==0)
{
backup=in1;
delay1(20);
if(backup!=in1)continue;
while(in1!=1);
ConfigBuffer[i]=table[4];TimerT0[i]=4;break;
}
if(in2==0)
{
backup=in2;
delay1(20);
if(backup!=in2)continue;
while(in2!=1);
ConfigBuffer[i]=table[5];TimerT0[i]=5;break;
}
if(in3==0)
{
backup=in3;
delay1(20);
if(backup!=in3)continue;
while(in3!=1);
ConfigBuffer[i]=table[6];TimerT0[i]=6;break;
}
if(in4==0)
{
backup=in4;
delay1(20);
if(backup!=in4)continue;
while(in4!=1);
ConfigBuffer[i]=table[7];TimerT0[i]=7;break;
}
P3=0xfb;
if(in1==0)
{
backup=in1;
delay1(20);
if(backup!=in1)continue;
while(in1!=1);
ConfigBuffer[i]=table[8];TimerT0[i]=8;break;
}
if(in2==0)
{
backup=in2;
delay1(20);
if(backup!=in2)continue;
while(in2!=1);
ConfigBuffer[i]=table[9];TimerT0[i]=9;break;
}
}
}
Timerflag=TimerT0[3]*1000+TimerT0[2]*100+TimerT0[1]*10+TimerT0[0];
P3=0xff;
EA=1;
break;
}
}
}
REN=1;
}
复制代码
作者:
admin
时间:
2018-7-10 03:48
能分享下原理图吗?
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1