1、AVR AD采集转换程序,带数字滤波 1. //本例使用内部参考电压,ADc0输入,采集的信号通过LED显示。 2. 3. //ICC-AVR application builder : 2006-9-3 11:42:36 4. // Target : M32 5. // Crystal: 7.3728Mhz 6. // 2.56v 片内基准电压,输入a1:即adc0 7. // 误差为: 连续测量模式。 8. // 精度8,输出左对齐 ADLAR=1 9. // 注意:参考电压一定要高于被测电压。 10. #i
2、nclude
3、 uint8 value,value1=0; 20. int x; //最终的值 10位 21. volatile uint8 i,j=0; 22. 23. //delay 24. /***********************************/ 25. void Delay100us(uint8 n) 26. { 27. uint8 i; 28. for(i=36;n!=0;n--) 29. while(--i); 30. } 31. 32. void Delay1s(uint8
4、 n) 33. { 34. n=n*10; 35. for (;n!=0;n--){ 36. Delay100us(200); 37. } 38. } 39. /******************************/ 40. 41. void port_init(void) 42. { 43. PORTA = 0x00; //做adc输入时不可上拉。 44. DDRA = 0x00; 45. PORTB = 0xFF; 46. DDRB = 0xFF; 47. PORT
5、C = 0xFF;
48. DDRC = 0x00;
49. PORTD = 0xFF;
50. DDRD = 0x00;
51. }
52.
53. //ADC initialize
54. // Conversion time: 225uS
55. void adc_init(void)
56. {
57. ADCSR = 0x00; //disable adc
58. ADMUX = 0xC0|(1< 6、 0x80; // 使能adc可用,不用修改
60. ADCSRA = 0xA8; // ADC使能,自动触发模式使能,触发源由SFIOR确定,中断使能,分频因子为2
61. SFIOR = 0X60; // 触发源设置为:定时器比较匹配
62. }
63.
64. //TIMER0 initialize - prescale:1024
65. // WGM: Normal
66. // desired value: 1Hz
67. // actual value: 35.556mSec (-3455.6%)
68. void time 7、r0_init(void)
69. {
70. TCCR0 = 0x00; //stop
71. TCNT0 = 0x01; //set count
72. OCR0 = 0x02; //set compare //FF
73. TCCR0 = 0x0D; //start timer 1024分频 CTC比较输出 定时时间:256/(7.3728Mhz/1024)=35.556ms
74. }
75.
76. #pragma interrupt_handler timer0_ovf_isr:10
77. void timer0_ovf_ 8、isr(void)
78. {
79. TCNT0 = 0x01; //reload counter value
80. j++;
81. if(j==0) CLI();
82. }
83.
84. #pragma interrupt_handler timer0_comp_isr:20
85. void timer0_comp_isr(void)
86. {
87. //compare occured TCNT0=OCR0
88. TCNT0 = 0x01; //reload counter value
89. i+ 9、
90. if(i==0) CLI();
91. }
92.
93. #pragma interrupt_handler adc_isr:15
94. void adc_isr(void)
95. {
96. //conversion complete, read value (int) using...
97. //ADIF 硬件清零
98. ADCSRA |= (1< 10、 100. // value|=(int)ADCH << 8; //read 2 high bits and shift into top byt
101. //value=(value*2.56)/1024;
102. //数字滤波
103. value1=(char)(((int)a*value1 + (int)b*value)>>8);
104. //value1=(int)(a*value1+b*value);
105. x = 0|value1;
106. x= x <<2; //真实的10位值
107. if(((x/100)<16)&&((x/100) 11、>0))
108. PORTB = led_table[x/100];
109. else PORTB = led_table[0];
110. /*/测试
111. j++;
112. if(j==255)
113. {
114. //TIMSK = 0x00;
115. ADCSRA&=~(1< 12、lize all peripherals
123. void init_devices(void)
124. {
125. //stop errant interrupts until set up
126. CLI(); //disable all interrupts
127. port_init();
128. timer0_init();
129. adc_init();
130.
131. MCUCR = 0x00; //电源管理项
132. GICR = 0x00; //boot 选项
133. TIMSK = 0x03; //time 13、r interrupt sources 比较输出
134. SEI(); //re-enable interrupts
135. //all peripherals are now initialized
136. }
137.
138. void main(void)
139. {
140. init_devices();
141.
142. ADCSRA|=(1< 14、
148. // while ((ADCSR&(1< 15、// Target : M32
// Crystal: 7.3728Mhz
// 2.56v 片内基准电压,输入a1:即adc0
// 误差为: 连续测量模式。
// 精度8,输出左对齐 ADLAR=1
// 注意:参考电压一定要高于被测电压。
#include 16、0x80,0x90,0x88,0x86,0xc7,0xc4,0x83,0x8b};// 0~~f
typedef unsigned char uint8;
uint8 value,value1=0;
int x; //最终的值 10位
volatile uint8 i,j=0;
//delay
/***********************************/
void Delay100us(uint8 n)
{
uint8 i;
for(i=36;n!=0;n--)
while(--i);
}
void Delay1s(uint8 17、n)
{
n=n*10;
for (;n!=0;n--){
Delay100us(200);
}
}
/******************************/
void port_init(void)
{
PORTA = 0x00; //做adc输入时不可上拉。
DDRA = 0x00;
PORTB = 0xFF;
DDRB = 0xFF;
PORTC = 0xFF;
DDRC = 0x00;
PORTD = 0xFF;
DDRD = 0x00;
}
//ADC initialize
// Conversion t 18、ime: 225uS
void adc_init(void)
{
ADCSR = 0x00; //disable adc
ADMUX = 0xC0|(1< 19、 Normal
// desired value: 1Hz
// actual value: 35.556mSec (-3455.6%)
void timer0_init(void)
{
TCCR0 = 0x00; //stop
TCNT0 = 0x01; //set count
OCR0 = 0x02; //set compare //FF
TCCR0 = 0x0D; //start timer 1024分频 CTC比较输出 定时时间:256/(7.3728Mhz/1024)=35.556ms
}
#pragma interrupt_handler timer0_ov 20、f_isr:10
void timer0_ovf_isr(void)
{
TCNT0 = 0x01; //reload counter value
j++;
if(j==0) CLI();
}
#pragma interrupt_handler timer0_comp_isr:20
void timer0_comp_isr(void)
{
//compare occured TCNT0=OCR0
TCNT0 = 0x01; //reload counter value
i++;
if(i==0) CLI();
}
#pragma interrupt_han 21、dler adc_isr:15
void adc_isr(void)
{
//conversion complete, read value (int) using...
//ADIF 硬件清零
ADCSRA |= (1< 22、ue1=(char)(((int)a*value1 + (int)b*value)>>8);
//value1=(int)(a*value1+b*value);
x = 0|value1;
x= x <<2; //真实的10位值
if(((x/100)<16)&&((x/100)>0))
PORTB = led_table[x/100];
else PORTB = led_table[0];
/*/测试
j++;
if(j==255)
{
//TIMSK = 0x00;
ADCSRA&=~(1< 23、ed_table[0];
}
*/
}
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
timer0_init();
adc_init();
MCUCR = 0x00; //电源管理项
GICR = 0x00; //boot 选项
TIMSK = 0x03; //timer interrupt 24、 sources 比较输出
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
void main(void)
{
init_devices();
ADCSRA|=(1< 25、/ Delay1s(1);
}
}
这两天在看别人写的AVR中AD转换程序,自已拼凑起一个能用的,觉得蛮好玩。贴出来共享
下面这个程序在ATMEGA16L上通过,直接在LCM上显示PA0口的电压。单位是0.1mV
本程序只是偶试验AVR的AD转换功能而写,也并非我原创,只是消化了别人的程序凑起来的。但绝对能用。
同时也望大虾们指点一二。
//单端通道,不放大
#define AD_SE_ADC0 0x00 //ADC0
#define AD_SE_ADC1 0x01 //ADC1
#define AD_SE_ADC2 0x02 //ADC2 26、
#define AD_SE_ADC3 0x03 //ADC3
#define AD_SE_ADC4 0x04 //ADC4
#define AD_SE_ADC5 0x05 //ADC5
#define AD_SE_ADC6 0x06 //ADC6
//常量定义
#define Vref 2650 //mV
/*********AD转换函数******************/
//AD转换函数
//ADC_PORT为输入的端口
/**************************************/
uint16_t Measured_Vol_I 27、NT(unsigned char ADC_PORT)
{
uint16_t M_Volt=0; //变换后的电压mV
uint32_t temp32;
uint8_t i;
ADMUX=0xC0|ADC_PORT; //片内基准电压,单端输入.
/*
ADMUX (ADC Multiplexer Select Register)
bit7 bit6
REFS1 REFS0 参考电压选择
28、 0 0 AREF,内部Vref关闭
0 1 AVCC,AREF引脚外加滤波电容
1 0 保留
1 1 2.56V的片内基准电压源,AREF引脚外加滤波电容
bit5 ADC结果左对齐选择 1=左对齐 0=右对齐
bit4~0 选择32通道
*/
ADCSRA=(1< 29、1< 30、 bit2:0 ADC 预分频选择位 111=128时钟分频
*/
asm ("sleep");
for(i=0;i<24;i++)
{
ADCSRA|=(1< 31、 temp32=(uint32_t)ADC*Vref;
M_Volt+=(uint16_t)(temp32/1023);
}
ADCSRA&=~(1< 32、); /*延时100ms*/
Lcminit(); /*液晶模块初始化 */
myprintf("mV%");
while(1)
{
DelayMs(500); /*延时500ms*/
col=0;row=2;
myprintf(" %");
col=60;row=2;
show_long((unsigned long)Measured_Vol_INT(AD_SE_ADC0));//获取端口PA0的转换数据
}
}
系统功能
大部分 33、AVR内部带有AD,本节以使用ATMEGA16的内部AD为例,给出AD转换中断程序。
硬件设计
AVR主控电路原理图(点击图片放大,不需要放大镜!)
AD转换值低位,LED控制电路原理图(点击图片放大,不需要放大镜!)
AD转换值高位,LED控制电路原理图(点击图片放大,不需要放大镜!)
软件设计
下面部分从TXT拷出,拷到网页,代码部分缺省了很多空格,比较凌乱,请谅解!
//目标系统: 基于AVR单片机
//应用软件: ICC AVR
/*01010101010101010101010101010101010101010101010101010101 34、010101010101
----------------------------------------------------------------------
实验内容:
使用中断检测AD0口,使用PB/PD口的LED指示AD读到的数据。
----------------------------------------------------------------------
硬件连接:
将“ADJ0.AD0”引针与“MCU.AD0” 引针使用短路帽短接。
将PB/PD口的LED指示灯使能开关切换到"ON"状态。
--------------------------- 35、
注意事项:
(1)若有加载库程序,请将光盘根目录下的“库程序”下的“ICC_H”文件夹拷到D盘
(2)请详细阅读:光盘根目录下的“产品资料\开发板实验板\SMK系列\SMK1632\说明资料”
----------------------------------------------------------------------
10101010101010101010101010101010101010101010101010101010101010101010*/
#include 36、 37、
程序名称:AD转换初始化程序
程序功能:
注意事项:
提示说明:
输 入:
返 回:
--------------------------------------------------------------------*/
void adc_init()
{
/* 设置对应的IO口为输入高阻态 */
DDRA &= ADEnStatus[AdcMux];
PORTA &= ADEnStatus[AdcMux];
A 38、DCSRA = 0x00; //disable adc
ADMUX = (1< 39、中断服务程序
程序功能:
注意事项:
提示说明:
输 入:
返 回:
--------------------------------------------------------------------*/
#pragma interrupt_handler adc_isr:15
void adc_isr(void)
{
AdcVal = ADC&0x3FF;
ADMUX = (1< 40、conversion
}
/*--------------------------------------------------------------------
程序名称:
程序功能:
注意事项:
提示说明:
输 入:
返 回:
--------------------------------------------------------------------*/
void main(void)
{
H_VAL_DISP_DDR = 0xFF;
L_VAL_DISP_DDR = 0xFF;
AdcMux = 0; //使用 41、ADC通道0
adc_init();
SEI();
while(1)
{
H_VAL_DISP_PORT = (AdcVal&0x300)>>8; //ADC的高2位Val
L_VAL_DISP_PORT = AdcVal&0xFF; //ADC的低8位Val
}
}
#include "iom16v.h"
/*20080905成功 ICC AVR 6.31A ATMEGA16
硬件连接 PA0模拟输入,接电位器抽头 PB口输出,接8个LED*/
#include 42、//定义了一些常用的宏 加入20080904
#define uchar unsigned char
#pragma interrupt_handler ad_handler:15
uchar addata;
//模数转换完成中断
void ad_handler(void)
{
addata=ADCH;
PORTB=~(addata); //取反用LED显示
ADCSRA|=BIT(ADSC); //启动下一次转换 ADCSR状态寄存器 ADSC模数转换启动位
//ADCSR|=(1< 43、//
}
//主程序
void main()
{
PORTA=0; //无上拉
DDRA=0; //设置PA口为输入
PORTB=0xff;
DDRB=0xff;
// ADMUX=0x00; //选择第0通道 屏蔽20080905
ADMUX=0x60; //基准AVCC,左对齐选择第0通道 加入
ADCSRA=0xCE; //采用单次转换模式,64分频
ADCSRA|=BIT(ADSC); //启动一次哑转换
//ADCSR|=(1<






