//用STC12C5A单片机内部AD连续采集126个数据
//将其处理后送12864液晶屏显示
//横坐标代表时间,纵坐标代表电压
//延时后更新下一屏
//2014.3.7日试验基本成功
//2014.3.10日试验基本成功,刚上电时按下不同按钮可取不同的采样周期
//缺点只能测正电压,显示交流电半个波形
//无同步触发功能
//按键扫描程序是用来调整 每次采集的时间间隔,以便适于不同频率 如果不用,需要给m设1初值
//信号输入引脚为p1.0
#include<STC12C5A.H>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar idata tempdate[126]={0};
uchar temp1,temp2,m=166;
uchar keyval,key=16;
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
#define DB_DATA P0//液晶屏数据口
sbit BF=P0^7; //液晶显示忙检测位
sbit RS=P3^5;
sbit RW=P3^6;
sbit E=P3^4;
//sbit s1=P3^7;
sbit beep=P2^3;
sbit diola=P2^5;
sbit dula=P2^6;
sbit wela=P2^7;
sbit led1=P1^0;
sbit led2=P1^1;
sbit led3=P1^2;
sbit led4=P1^3;
sbit led5=P1^4;
void Delay_US(uchar us);//1延时
void Delay_MS(uchar ms);//2延时
void Delay_S(uchar s);//3 延时 本程序没用
void adchange();//4 AD 转换
void Chk_busy( void );//5 液晶屏忙检测
void Write_lcd( uchar dat_cmd,uchar content);//6写液晶屏
uchar Read_lcd(void);//7读液晶屏
void Lcd_inital(void); //8液晶屏初始化
void CollectorDot(uchar ch);//9 采集126个数据
void Clear(void);//10 清屏
void DisplayDot(uchar Hang,uchar lie);//11 显示1个点
void drawpicture();//12 画曲线
void lianxu_adchange();//13 连续采集多个数据,用于高速采集 本程序没用
void Delay_10S( );//14
void Delay_500MS( );//15
void DISPLAY(uint bb);//16数码管显示,可以不要
void CollectorDot100();//17本程序没用
void keyscan();//18 按键扫描,可以不要
void Delay_US(uchar us)//1 延时
{
while(--us);
}
void Delay_MS(uchar ms)//2
{
do {Delay_US(246);Delay_US(247);}
while(--ms);
}
void Delay_S(uchar s)//3 本程序没用
{
do{Delay_MS(200);Delay_MS(200);Delay_MS(200);Delay_MS(200);Delay_MS(200);}
while(--s);
}
void adchange()//4
{
ADC_CONTR=ADC_CONTR|0X80; //10000000 开启转换电源
//延时,等待内部电源稳定,同时调节采集周期
Delay_US(m);//500 US每次166 200US对应61 100us每次应改为27 50US对应9
Delay_US(m);
Delay_US(m);
Delay_US(m);
P1M0=P1M0|0X03; //设置p1.0和P1.1所在通道为开/漏模式
P1M1=P1M1|0X03;
ADC_CONTR=0xe0; //11100000 开启P1.0通道开始转换
Delay_US(m); //延时一端时间,使输入电压达到稳定
Delay_US(m);
ADC_RES =0x00; //清A/D转换结果寄存器
ADC_RESL =0x00;
ADC_CONTR |= 0x08; //ADC_START=1,开始转换
while(!(ADC_CONTR&0x10)); //0001,0000 等待A/D转换结束
temp1=ADC_RES; //读取转换结果,共10位只要高8位
//temp2=ADC_RESL;
ADC_CONTR=ADC_CONTR&0xe7; //将ADC_FLAG软件清零
Delay_US(m);
Delay_US(m);
P1M0=P1M0&0X00; //设置P1口为普通I/O模式,以便用P1口显示数据。
P1M1=P1M1&0X40;
}
//每次采集除延时外,大约19 US
void Chk_busy(void)//5 判断是否忙,实际是等待忙完
{
DB_DATA=0xff;
RS=0;
RW=1;
E=1;
while(BF);
E=0;
}
void Write_lcd( uchar dat_cmd,uchar content)//6 写液晶屏(命令或数据)
{
Chk_busy();
RS=dat_cmd;//0 命令,1数据
RW=0;
E=1;
DB_DATA=content;
E=0;
}
uchar Read_lcd(void)//7 读液晶屏
{
uchar rddata;
Chk_busy();
RS=1;
RW=1;
E=1;
rddata=DB_DATA;
E=0;
return rddata;
}
void Lcd_inital(void) //8 Lcd初始化
{
dula=1;
wela=1;
P0=0xff;
dula=0;
wela=0;
// diola=1;
Write_lcd(0,0x30); //功能设定,8位接口控制,选择普通指令(禁止了扩展指令)
Write_lcd(0,0x30); //同一指令的动作不能同时改变RE 及DL、G,需先改变DL 或G 再改变RE 才
Write_lcd(0,0x0c); //整体显示开,游标位置显示关,游标位置反白关
Write_lcd(0,0x01); //清除显示
Write_lcd(0,0x06); //画面设定,游标右移,画面不移动
}
void CollectorDot()//9
{
uchar i;
for(i=0;i<126;i++)
{
adchange();
tempdate[ i]=temp1;
}
}
void Clear(void)//10 清屏
{
uchar i,j,k;
k=0x80;
Write_lcd(0,0x34); //扩充功能设定,同时关绘图显示
for(i=0;i<32;i++)
{
Write_lcd(0,0x80+i);
Write_lcd(0,k);
for(j=0;j<16;j++)
Write_lcd(1,0x00);
}
k=0x88;
for(i=0;i<32;i++)
{
Write_lcd(0,0x80+i);
Write_lcd(0,k);
for(j=0;j<16;j++)
Write_lcd(1,0x00);
}
Write_lcd(0,0x36); //扩充功能设定,同时开绘图显示
Write_lcd(0,0x30);
}
void DisplayDot(uchar Hang,uchar lie)//11 行y 0-63 列x 0-127
{
uchar hang,lie1,lie2,data1,data2;
Write_lcd(0,0x34);
lie1=lie/16; //列号 0-7
lie2=lie%16; // 列内号 0-15
if(Hang<32)hang=Hang; //Y坐标32以内,行号=Y坐标
else
{
lie1+=8;
hang=Hang-32;// Y坐标32~64之间,行号=Y坐标-32
}
Write_lcd(0,0x80+hang);//写行号
Write_lcd( 0,0x80+lie1 );//写列号
Read_lcd();//这一句还真有点用,但不知干什么的
data1=Read_lcd( );//读出原来数据,,除要写点位置外,原数据不变
data2=Read_lcd( );
Write_lcd(0,0x80+hang);
Write_lcd( 0,0x80+lie1 );
if((lie2>=0)&&(lie2<=7))//1 个列地址对应两个字节 0-7是1个字节,8-15是第2个字节
{
Write_lcd(1,data1|(0x01<<(7-lie2)));//改变第1个字节内容(插人所要画的点)
Write_lcd(1,data2);//第二个字节内容不变
}
elseif((lie2>=8)&&(lie2<=15))
{
Write_lcd(1,data1);//第1个字节内容不变
Write_lcd(1,data2|(0x01<<(15-lie2)));//改变第2个字节内容(插人所要画的点)
}
Write_lcd(0,0x36);
Write_lcd(0,0x30);
}
void drawpicture()//12 画图
{
uchar dot,x,y1,y2;
for(dot=0;dot<126;dot++)
{
x=dot;
y1=tempdate[dot]/4;
y2=63-y1;
DisplayDot(y2,x);
}
}
void Delay_500MS( )//1
{
uint bb=6667;
while(bb>0)
{
Delay_US(200);
bb--;
}
}
void main ()
{
Lcd_inital(); //初始化
diola=1;
while(key==16){keyscan();}
switch(key)
{
case 0:m=9;led2=0;break;
case 1:m=27;led3=0;break;
case 2:m=61;led4=0;break;
case 4:m=166;led5=0;break;
default:break;
}
while(1)
{
CollectorDot();//采集126个数据
//CollectorDot100();//采集100个数据并显示所花时间
Clear(); //清屏
drawpicture(); //画图
Delay_500MS( );
//s1=0;
Delay_MS(250); //延时约47ms
Delay_500MS( );
}
}
void lianxu_adchange()//13 连续采集多个数据一次开启,多次采集适合于高速
{
uchar i;
ADC_CONTR=ADC_CONTR|0X80; //10000000 开启转换电源
Delay_MS(1); //延时,等待内部电源稳定
//Delay_US(100);
P1M0=P1M0|0X03; //设置p1.0和P1.1所在通道为开/漏模式
P1M1=P1M1|0X03;
for(i=0;i<120;i++)
{
ADC_CONTR=0xe0; //11100000 开启P1.0通道开始转换
Delay_US(50); //延时一端时间,使输入电压达到稳定
ADC_RES =0x00; //清A/D转换结果寄存器
ADC_RESL =0x00;
ADC_CONTR |= 0x08; //ADC_START=1,开始转换
while(!(ADC_CONTR&0x10)); //0001,0000 等待A/D转换结束
tempdate[ i]=ADC_RES; //读取转换结果,共10位只要高8位
ADC_CONTR=ADC_CONTR&0xe7; //将ADC_FLAG软件清零
Delay_US(20);
}
P1M0=P1M0&0X00; //设置P1口为普通I/O模式,以便用P1口显示数据。
P1M1=P1M1&0X40;
}
void CollectorDot100()//9 用于计算并显示采集100次所花时间
{
uchar i;
uint AA;
TMOD=0X01;
TH0=0;
TL0=0;
TR0=1;
for(i=0;i<100;i++)
{
adchange();
tempdate[ i]=temp1;
}
TR0=0;
AA=TH0*256+TL0;
DISPLAY(AA);
}
void DISPLAY(uint bb)
{
uint i;
uchar b1,b2,b3,b4,b5;
b1= bb/10000%10;
b2= bb/1000%10;
b3= bb/100%10;
b4= bb/10%10;
b5= bb%10;
for(i=0;i<2000;i++)
{
wela=1;
DB_DATA=0xfe;
wela=0;
dula=1;
DB_DATA=table[b1];
dula=0;
Delay_MS(10);
wela=1;
DB_DATA=0xfd;
wela=0;
dula=1;
DB_DATA=table[b2];
dula=0;
Delay_MS(10);
wela=1;
DB_DATA=0xfb;
wela=0;
dula=1;
DB_DATA=table[b3];
dula=0;
Delay_MS(10);
wela=1;
DB_DATA=0xf7;
wela=0;
dula=1;
DB_DATA=table[b4];
dula=0;
Delay_MS(10);
wela=1;
DB_DATA=0xef;
wela=0;
dula=1;
DB_DATA=table[b5];
dula=0;
Delay_MS(10);
}
}
void keyscan()
{
uchar temp;
P3=0xef;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
Delay_MS(20);
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0xee:
key=0;
break;
case 0xed:
key=4;
break;
case 0xeb:
key=8;
break;
case 0xe7:
key=12;
break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
beep=0;
}
beep=1;
}
}
P3=0xdf;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
Delay_MS(20);
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0xde:
key=1;
break;
case 0xdd:
key=5;
break;
case 0xdb:
key=9;
break;
case 0xd7:
key=13;
break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
beep=0;
}
beep=1;
}
}
P3=0xbf;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
Delay_MS(20);
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0xbe:
key=2;
break;
case 0xbd:
key=6;
break;
case 0xbb:
key=10;
break;
case 0xb7:
key=14;
break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
beep=0;
}
beep=1;
}
}
P3=0x7f;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
Delay_MS(20);
if(temp!=0x0f)
{
temp=P3;
switch(temp)
{
case 0x7e:
key=3;
break;
case 0x7d:
key=7;
break;
case 0x7b:
key=11;
break;
case 0x77:
key=15;
break;
}
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
beep=0;
}
beep=1;
}
}
} |