#include <stc.h>
#include <intrins.h>
#define RELOAD_COUNT 0xD7 //12.6 MHz,1T9600bps
/*----------------------------LCD1602接口定义----------------------------------*/
sbit LCD_RS= P2^5; //数据指令
sbit LCD_RW= P2^7; //读写控制端
sbit LCD_EN= P2^4; //使能端
/********************************显示数据表*********************************/
typedef unsigned char uchar;
uchar tmp;
uchar dis1[] = {"4 -.--V 5 -.--V"};
uchar dis2[] = {"I ----mA P -.--V"};
uchar channel;
uchar result[5];
long Data=500; //电压源电压值 v*100
void serial_port_initial(void); //定义串口
void delayms(uchar); //延时
void delayus(uchar us); //延时
void UART_Interrupt_Receive(void); //接收字符
void send_char(uchar); //发送字符
void send_str(uchar stLCD_RS[]); //发送字符串
uchar get_AD_result(uchar); //AD转换
void lcd_en(void); //输入使能
void lcd_wcmd (uchar cmd) ;
void lcd_wdat (uchar dat) ;
void lcd_printc (uchar x, uchar y, uchar c) ;
void lcd_prints (uchar x, uchar y, uchar *s) ;
bit lcd_bz();
/**********************LCD延时子程序********************************/
void delayms(uchar ms) //LCD延时子程序
{ uchar a,b;
while(ms--)
{
for(b=233;b>0;b--)
for(a=12;a>0;a--);
}
}
void delayus(uchar us) //1us相当于
{
uchar a;
while(us--)
{
a++;
a--;
}
}
/*****************************************************************************
函数功能:显示相关程序
*****************************************************************************/
void lcd_init() //函数功能:LCD初始化子程序
{
lcd_wcmd(0x28); //四线显示
delayms(1);
lcd_wcmd(0x0c); //显示打开
delayms(1);
lcd_wcmd(0x06);
delayms(1);
lcd_wcmd(0x01); //显示清屏
delayms(1);
}
void lcd_en(void) //输入使能
{
LCD_EN = 1;
delayus(10); //10us
LCD_EN = 0;
}
bit lcd_bz()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delayus(50);
result = (bit)(P2 & 0x08);
LCD_EN = 0;
return result;
}
/*****************************************************************************
函数功能:写指令数据到LCD子程序
入口参数:cmd
出口参数:
*****************************************************************************/
void lcd_wcmd(uchar cmd)
{
while(lcd_bz()); //判断LCD是否忙碌
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
P2 &= 0xf0; //清低四位
P2 |= (cmd&0xf0)>>4; //写低四位
lcd_en();
P2 &= 0xf0; //清低四位
P2 |= cmd&0x0f; //写低四位
lcd_en();
}
/*****************************************************************************
函数功能:写入显示数据到LCD子程序
入口参数:dat
出口参数:
*****************************************************************************/
void lcd_wdat(uchar dat)
{
while(lcd_bz()); //判断LCD是否忙碌
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P2 &= 0xf0; //清低四位
P2 |= (dat&0xf0)>>4; //写低四位
lcd_en();
P2 &= 0xf0; //清低四位
P2 |= dat&0x0f; //写低四位
lcd_en();
}
void lcd_printc (uchar x, uchar y, uchar c) //字符定位输出
{
if(y) lcd_wcmd(x | 0xc0); //液晶定位
else lcd_wcmd(x | 0x80);
lcd_wdat(c);
}
void lcd_prints (uchar x, uchar y, uchar *s) //字符串定位输出
{
if(y) lcd_wcmd(x | 0xc0); //液晶定位
else lcd_wcmd(x | 0x80);
while(*s)
{
lcd_wdat(*s);
s++;
}
}
/************************主程序************************************/
void main(void)
{ // 初始化串口
serial_port_initial();
lcd_init(); // 初始化LCD
P1ASF=0xff ; // 0110,0011,要设置为 A/D 转换的P1.x 口,先设为高
channel=4;
while(1){
get_AD_result(channel);
dis1[0]=channel+48 ;
dis1[2]=result[0];
dis1[4]=result[1];
dis1[5]=result[2];
get_AD_result(5);
dis1[11]= result[0];
dis1[13]= result[1];
dis1[14]= result[2];
get_AD_result(6);
if(result[3]>=0x7e){result[3]-=0x7e; dis2[1]='+';} else {result[3]=0x7e-result[3]; dis2[1]='-';} //127==0x7f
Data= result[3]*5;
dis2[2]=Data/1000+48 ; // 返回 A/D 转换结果
dis2[3]=(Data%1000)/100+48 ;
dis2[4]=((Data%100)/10)+48 ;
dis2[5]=(Data%10)+48 ;
Data=63750/(get_AD_result(7)); //Data=255*250/result
dis2[11]= Data/100+48;
dis2[13]= (Data%100)/10+48;
dis2[14]= Data%10+48;
lcd_prints (0,0,dis1);
lcd_prints (0,1,dis2);
if(result[3]=='k')
{
while(1)
{
send_char(get_AD_result(channel));
delayms(100);
}
}
}
}
/*********************串口相关程序********************************/
void serial_port_initial() //定义串口初始值
{
PCON = 0x00; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器1时钟为Fosc,即1T
AUXR &= 0xfe; //串口1选择定时器1为波特率发生器
TMOD = 0x20;
TL1 = RELOAD_COUNT; //设定定时初值
TH1 = RELOAD_COUNT; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
EA = 1;
ES = 1;
}
void send_char(uchar i) //发送单字符
{
SBUF = i;
while(TI ==0); //等待发送完成
TI = 0; //清零串口发送完成中断请求标志
}
void send_str(uchar stLCD_RS[]) // 发送字符串
{
uchar i=0;
ES = 0; //关串口中断
TI = 0; //清零串口发送完成中断请求标志
while(stLCD_RS != '\0')
{
SBUF = stLCD_RS;
while(!TI); // 等特数据传送
TI = 0; //清零串口发送完成中断请求标志
i++; // 下一个字符
}
ES = 1; //允许串口中断
}
void UARTInterrupt(void) interrupt 4 //串口中断接收
{
if(RI) // 是否有数据到来
{
RI=0;
result[3] = SBUF; // 暂存接收到的数据
if(result[3]<8)
{
channel =result[3];
result[3]=get_AD_result(channel);
send_str("第");
send_char(channel+48);
send_str("通道电压是: ");
send_char(result[0]);
send_char('.');
send_char(result[1]);
send_char(result[2]);
send_char('V');
send_char(' ');
}
if(result[3]=='p')
{
result[3]=get_AD_result(7);
Data=63750/(result[3]);
send_str("芯片供电电压是: ");
send_char(Data/100+48);
send_char('.');
send_char((Data%100)/10+48);
send_char(Data%10+48);
send_char('V');
send_char(' ');
}
}
}
/**********************AD转换程序********************************/
uchar get_AD_result(uchar channell) //
{
uchar AD_finished = 0; // 存储 A/D 转换标志
ADC_CONTR=0xE0; //设置速度 0xx00000 打开电源 x0000000
ADC_RES = 0;
ADC_CONTR |= channell; // 选择 A/D 当前通道
delayms(1); //使输入电压达到稳定
ADC_CONTR |= 0x08; //0000,1000 令 ADC_START = 1, 启动A/D 转换
AD_finished = 0;
while ( AD_finished == 0 ) // 等待A/D 转换结束
{
AD_finished = (ADC_CONTR & 0x10); //0001,0000, ADC_FLAG ==1测试A/D转换结束否
}
ADC_CONTR &= 0xE0; //1110,0000 令 ADC_START = 0, 关闭A/D 转换,
result[3]=ADC_RES;
result[0]=result[3]*Data/25500+48 ; // 返回 A/D 转换结果
result[1]=((result[3]*Data/255)%100)/10+48 ;
result[2]=(result[3]*Data/255)%10+48 ;
return (result[3]);
}
|