MEGA16 ADC 加液晶显示

好友帅峰的技术文章,帅峰电子科技淘宝店

//定时器初值计算,定时1ms,1024分频为例,(255 – 130)*(T_CPU*64)=0.001s
//主机液晶显示调试  11.7.24
#include <mega16.h>
#include <delay.h>
#define uchar unsigned char
#define uint  unsigned
uint  ADC_data,ADC_real_data;
uint time,t;
uchar  SET_ADC,num;
bit  ADC_flag,time_ok;

#define LED    PORTB.7

#define LCD    PORTD      //1602_LCD_8位并行数据
#define RS       PORTB.0
#define RW     PORTB.1
#define E         PORTB.2

uint ADC_data_store[3];  //AD数据缓存

uchar    lcd_1602_table[]= ”  <MEGA 16> ADC   “;
uchar  lcd_1602_table1[]= ”  DC= 0000 mV          “;

void write_1602_com(uchar com)    // 写指令到1602LCD
{
RS=0;
RW=0;
E=0;
LCD=com;
delay_ms(1);
E=1;
delay_ms(1);
E=0;
}

void write_1602_data(uint date)   // 写数据到1602LCD
{
RS=1;
RW=0;
E=0;
LCD=date;
delay_ms(1);
E=1;
delay_ms(1);
E=0;
}

void  lcd_1602_init()
{
E=0;
write_1602_com(0x38); //设置1602显示,5*7点阵,8位数据接口
write_1602_com(0x0C); //
write_1602_com(0x06); //指令码设置
write_1602_com(0x01); //数据指针清零,所有显示清零
write_1602_com(0x80); //数据地址指针位.下一行的话  就是0x80+0x40+第几个,上一行就是0x80+第几个
}

void write_lcd_data(uchar x,uchar y,uint date) //数字提取数据子函数
{
uchar shi,ge,bai,qian,x_;
qian=date/1000;
bai=date%1000/100;
shi=date%100/10;
ge=date%10;
if(x==0) x_=0;
if(x==1) x_=0x40;
write_1602_com(0x80+x_+y);
write_1602_data(0x30+qian);
write_1602_data(0x30+bai);
write_1602_data(0x30+shi);
write_1602_data(0x30+ge);
}
uint ADC_conv(uint i)     //这里我们要将实际值放大1000倍计算,目的是不让单片机进行复杂的浮点数运算
{
long x;
uint y;
x=(4910*(long)i)/1023; //输入电压值/1023*adc
y=(uint)x;                       //将无符号长整型变量X转化为无符号整型变量Y
return y;                       //取Y数据转换返回值
}

interrupt [ADC_INT] void adc_isr(void)
{

ADC_data=ADCL;
ADC_data|=(int)ADCH<<8;           //将ADCH右对齐的低两位左移到高位,并和ADCL相加。
SET_ADC++;                                   //完成一次转换自加1
if(SET_ADC==1) ADMUX= 0x40; //选择通道0
if(SET_ADC==3) ADMUX= 0x41; //选择通道1 //如果要通道3加一句就行,记住数据缓冲区也改大一些
if(SET_ADC==4) SET_ADC=0;
ADC_flag=1;                                    //转换完成标志位

}

void AD_init( )
{
ADMUX |= (0<<REFS1)|(0<<REFS0)|(0<<ADLAR)|(0<<MUX4)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0);//初始化通道0
ACSR =0X80; //关模拟比较器
ADCSRA |= (1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(0<<ADIF)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}

void TC0_init()
{
TCCR0=0X00; //先停止定时器0,无时钟源所以停止
TCNT0=130;  //设定初值
TCCR0=0X03; //预置分频为64,低2位设置为11 /启动定时器0
TIMSK=0X01; //打开定时器0中断
SREG|=0X80; //打开总中断
}
void main(void)
{

   PORTA=0X00; //高阻态
DDRA=0X00;  //设定为输入使能

   PORTB= 0XFF;//给端口写数据
DDRB=0xFF;  //设定为输出使能

PORTC=0XFF; //给端口写数据
DDRC=0XFF;  //设定为输出使能

PORTD= 0XFF;//给端口写数据
DDRD=0xFF;  //设定为输出使能

SET_ADC=0;
TC0_init();
AD_init();
lcd_1602_init();

  for(num=0;num<16;num++)
{
write_1602_data( lcd_1602_table[num]);
delay_ms(1);
}
write_1602_com(0x80+40);  //第二行
for(num=0;num<16;num++)
{
write_1602_data( lcd_1602_table1[num]);
delay_ms(1);
}
t=0;
while(1)
{
if(ADC_flag==1)
{
ADC_flag=0;
ADC_real_data= ADC_conv(ADC_data);//数据转换
ADC_data_store[SET_ADC]=ADC_real_data;//存放到数组里

}

//  if(ADC_data_store[1] >2000) LED=0;

if(time_ok)   //500Ms刷新一次显示
{
write_lcd_data(1,6,ADC_data_store[3]);
time_ok=0;
}

 }

}

interrupt [TIM0_OVF] void timer0_ovf_isr(void) //定时器0中断
{
TCNT0=130;
time++;
if(time>=500)
{
time=0;
time_ok=1;
//    t++;
}
/* if(t>=6)
{
t=0;
adc1_ok=1;
}  */

}