⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 ATmega16内部ADC的应用:ATmega16内部集成了8路10位逐次逼近型模数转换器
💻 C
字号:
#include <iom16v.h>
#include <macros.h>
#include "lcd.h"
#include "usart.h"
#include "delay.h"
#define vref   256
volatile unsigned int extint_count=0;
volatile unsigned char act_flag=0;
volatile unsigned int adc_result;
unsigned char adc_show[6];
/** /
volatile:数据类型声明,表明该变量在程序执行中可被隐含改变
编译器有时会将SRAM中的数据拷贝到通用寄存器中以提高程序的执行效率
(在通用寄存器中对数据的操作速度比操作SRAM中的数据要快),这样会带来
一个问题,如果该SRAM中的数据已经被隐含改变(比如中断),那么编译器仍然
读取寄存器中之前的SRAM拷贝值显然与其实际值不同,从而出现错误。
本例中extint_count的值在外部中断服务程序中被改变,通过volatile
声明通知编译器。
/**/
void port_init(void)
{
 PORTA = 0xFE;
 DDRA  = 0xFE;
 PORTB = 0xFF;
 DDRB  = 0xFF;
 PORTC = 0xFF; 
 DDRC  = 0xFF;
 DDRD  = 0xFB;  //PD2(INT0)引脚设置为输入
 PORTD = 0xFB;  //关闭内部上拉
}
/*      AD转换程序     */
#pragma interrupt_handler adc_isr:15
void adc_isr(void)
{
   unsigned int temp=0;
   while(temp<6)
      temp++;                //短延时
   adc_result = ADC;         //读取AD转换值
	   
   ADCSRA |= (1<<ADSC);      //再次启动转换 			 	 		 
} 
void data_con(void)
{
   unsigned int temp;
   unsigned char i;
   temp=(unsigned int)(((unsigned long)((unsigned long)adc_result*vref))/1024);
   for(i=0;i<3;i++)
   {
	  adc_show[3-i]=temp%10+0x30;  //转换电压值用来在LCD上显示
	  temp=temp/10;
   }
	adc_show[0]=adc_show[1];
	adc_show[1]='.';	
	adc_show[4]='V';	
	adc_show[5]=0;	              //数组结束标记
}

#pragma interrupt_handler int0_isr:2
void int0_isr(void)
{
   extint_count++;
   if (act_flag!=1)
   {
      act_flag = 1;
   }
}
void adc_init(void)
{
   ADMUX = (1<<REFS1)|
           (1<<REFS0)|    //选择内部2.56v作为参考电压
           0x00;          //使用ad转换0通道
		                  //ADLAR = 0,转换结果选择右对齐
   ADCSRA = (1<<ADEN)|     //ADC使能
            (1<<ADSC)|     //开始一次ad转换
		    (1<<ADIF)|     //写1,将ADIF位清0
		    (1<<ADIE)|     //允许ADC中断
		    0x06;          //时钟分频系数为64
}
//call this routine to initialize all peripherals
void init_devices(void)
{
 CLI();         //关闭全局中断
 port_init();   //CPU端口初始化
 /**/
 MCUCR = 0x02;  //INT0引脚上的下降沿触发中断
 GICR  = 0x40;  //外部中断0请求使能
 /**/
 /** /
  MCUCR = 0x00;  //INT0引脚上的低电平触发中断
  GICR  = 0x40;  //外部中断0请求使能
 /**/
 /** /
  MCUCR = 0x01;  //INT0引脚上的上升沿和下降沿都触发中断
  GICR  = 0x40;  //外部中断0请求使能
 /**/
 /** /
  MCUCR = 0x03;  //INT0引脚上的上升沿触发中断
  GICR  = 0x40;  //外部中断0请求使能
 /**/
 adc_init();
 SEI(); //打开全局中断
 
}
void main(void)
{
   char temp_show[5];  //定义数组用作在液晶屏上进行显示
   unsigned char i;
   unsigned int temp;
   for(i=0;i<5;i++)
   {
      temp_show[i] = 0;
   }
   temp_show[4] = 0xff;  //显示结束标志
   /**/
   init_devices();
   LCDReady();
   LcdInit();          //LCD初始化
   CharsWrite(0,1,"AD0 VOLTAGE:");  //在LCD的第一行显示"AD0 VOLTAGE:"
   CharsWrite(0,2,"0.0V");            //在第二行显示“0.0V”
   uart_init();        //串口初始化
   delay_ms(1000);
   /**/
   while(1)
   {
      ClearLcd();     //清屏LCD
	  delay_us(80);   //等待清屏操作完成
	  CharsWrite(0,1,"AD0 VOLTAGE:");  //在LCD的第一行显示"AD0 VOLTAGE:"
	  data_con();                      //将ad转换值转换为电压值
	  CharsWrite(0,2,adc_show);        //在LCD上显示转换电压值
	  delay_ms(300);
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -