سلام.
دوستان من قسمت ADC از دیتاشیت ATmega32 رو خوندم و الان یک چالشی برام پیش اومده.
من میخوام که ADC با تایمر 0 (تطابق با OCR0) تریگر (راه اندازی) بشه و نمونه گیری کنه. برای همین کد پایینو نوشتم. اما مشکل اینجاست که اصلا کار نمی کنه !! یعنی اگرچه تایمر درست کار می کنه، ADC هم به تنهایی درست کار می کنه. اما ADC در زمان تطابق با OCR0 شروع به نمونه گیری نمی کنه !!
[code=c]/*
* ADC_TRIG.c
*
* Created: 9/22/2015 8:14:25 PM
* Author:
*/
#include <avr/io.h>
#define F_CPU 8000000UL // 8MHz
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include <avr/interrupt.h>
char Text[50]="";
#define Baudrate 9600
#define ADC_REF_VOL 2.56
#define ADC_VREF_TYPE (1<<REFS1) | (1<<REFS0)
uint16_t temp;
void Send_Data(uint8_t data);
void SendString(char *str);
uint16_t Read_ADC(uint8_t channel) ;
float ADCResult;
volatile uint16_t ADC_W;
volatile uint8_t ADC_f;
volatile uint8_t count;
ISR(TIMER0_COMP_vect)
{
//count++;
TIFR = (1<<OCF0);
//Read_ADC(0);
}
ISR(ADC_vect)
{
ADC_W=ADCW;
ADCSRA|=(1<<ADIF);
ADC_f = 1;
}
int main(void)
{
ADC_f = 0;
UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<PE) | (0<<U2X) | (0<<MPCM);
UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (0<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);
UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL);
temp=(F_CPU/16)/Baudrate;
UBRRH = (temp-1) / 256 ;
UBRRL = (temp-1) % 256 ;
TCCR0 = (0<<FOC0) | (0<<WGM01) | (0<<WGM00) | (0<<COM01) | (1<<COM00) | (1<<CS02) | (0<<CS01) | (1<<CS00); // ClkTimer = 8/1 = 8MHz
TCNT0 = 0;
OCR0 = 250;
TIMSK=(0<<OCIE2)|(0<<TOIE2)|(0<< TICIE1)|(0<<OCIE1A)|(0<<OCIE1B)|(0< <TOIE1)|(1<<OCIE0)|(0<<TOIE0);
DDRB|= (1<<3);
ADMUX = ADC_VREF_TYPE | (0<<ADLAR) | (0<<MUX4) | (0<<MUX3) | (0<<MUX2) | (0<<MUX1) | (0<<MUX0);
SFIOR = (0<<ADTS2) | (1<<ADTS1) | (1<<ADTS0);
ADCSRA = (1<<ADEN) | (0<<ADSC) | (1<<ADATE) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);
ADCSRA |=(1<<ADSC);
//ADCH;ADCL,ADCW;
sei();
while(1)
{
if ((PINC & 1<<PC0)==0)
{
_delay_ms(200);
temp = Read_ADC(0);
}
if (ADC_f==1)
{
ADCResult = (ADC_W*ADC_REF_VOL)/1024.0f;
sprintf(Text,"Voltage in ADC is = %3.3f Volt\n\r",ADCResult);
SendString(Text);
ADC_f = 0;
}
}
}
//---------------------------
void Send_Data(uint8_t data){
UDR=data;
while ( !( UCSRA & (1<<UDRE)) ); // wait until Transmit buffer be empty
UCSRA = (1<<TXC);
}
void SendString(char *str){
while(*str != 0){
Send_Data(*str++);
}
}
uint16_t Read_ADC(uint8_t channel)
{
ADMUX &= 0xE0;
ADMUX = ADC_VREF_TYPE | channel;
_delay_us(10);
ADCSRA|=(1<<ADSC);
return 1;
}[/code]
من از یک کلید متصل به پایه 0 از پورت C هم استفاد می کنم. با فشردن کلید ADC درست نمونه برداری می کنه. این هم برای نشون دادن صحت عملکرد واحد ADC گذاشتم.
پ.ن. طبق کد و دیتاشیت، واحد ADC باید تقریبا هر 32 میلی ثانیه یکبار کانال 0 رو نمونه براری کنه. این زمان از زمان لازم برای نمونه برداری هم بیشتره و از این نظر مشکلی نیست.
دوستان من قسمت ADC از دیتاشیت ATmega32 رو خوندم و الان یک چالشی برام پیش اومده.
من میخوام که ADC با تایمر 0 (تطابق با OCR0) تریگر (راه اندازی) بشه و نمونه گیری کنه. برای همین کد پایینو نوشتم. اما مشکل اینجاست که اصلا کار نمی کنه !! یعنی اگرچه تایمر درست کار می کنه، ADC هم به تنهایی درست کار می کنه. اما ADC در زمان تطابق با OCR0 شروع به نمونه گیری نمی کنه !!
[code=c]/*
* ADC_TRIG.c
*
* Created: 9/22/2015 8:14:25 PM
* Author:
*/
#include <avr/io.h>
#define F_CPU 8000000UL // 8MHz
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include <avr/interrupt.h>
char Text[50]="";
#define Baudrate 9600
#define ADC_REF_VOL 2.56
#define ADC_VREF_TYPE (1<<REFS1) | (1<<REFS0)
uint16_t temp;
void Send_Data(uint8_t data);
void SendString(char *str);
uint16_t Read_ADC(uint8_t channel) ;
float ADCResult;
volatile uint16_t ADC_W;
volatile uint8_t ADC_f;
volatile uint8_t count;
ISR(TIMER0_COMP_vect)
{
//count++;
TIFR = (1<<OCF0);
//Read_ADC(0);
}
ISR(ADC_vect)
{
ADC_W=ADCW;
ADCSRA|=(1<<ADIF);
ADC_f = 1;
}
int main(void)
{
ADC_f = 0;
UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<PE) | (0<<U2X) | (0<<MPCM);
UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (0<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);
UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL);
temp=(F_CPU/16)/Baudrate;
UBRRH = (temp-1) / 256 ;
UBRRL = (temp-1) % 256 ;
TCCR0 = (0<<FOC0) | (0<<WGM01) | (0<<WGM00) | (0<<COM01) | (1<<COM00) | (1<<CS02) | (0<<CS01) | (1<<CS00); // ClkTimer = 8/1 = 8MHz
TCNT0 = 0;
OCR0 = 250;
TIMSK=(0<<OCIE2)|(0<<TOIE2)|(0<< TICIE1)|(0<<OCIE1A)|(0<<OCIE1B)|(0< <TOIE1)|(1<<OCIE0)|(0<<TOIE0);
DDRB|= (1<<3);
ADMUX = ADC_VREF_TYPE | (0<<ADLAR) | (0<<MUX4) | (0<<MUX3) | (0<<MUX2) | (0<<MUX1) | (0<<MUX0);
SFIOR = (0<<ADTS2) | (1<<ADTS1) | (1<<ADTS0);
ADCSRA = (1<<ADEN) | (0<<ADSC) | (1<<ADATE) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);
ADCSRA |=(1<<ADSC);
//ADCH;ADCL,ADCW;
sei();
while(1)
{
if ((PINC & 1<<PC0)==0)
{
_delay_ms(200);
temp = Read_ADC(0);
}
if (ADC_f==1)
{
ADCResult = (ADC_W*ADC_REF_VOL)/1024.0f;
sprintf(Text,"Voltage in ADC is = %3.3f Volt\n\r",ADCResult);
SendString(Text);
ADC_f = 0;
}
}
}
//---------------------------
void Send_Data(uint8_t data){
UDR=data;
while ( !( UCSRA & (1<<UDRE)) ); // wait until Transmit buffer be empty
UCSRA = (1<<TXC);
}
void SendString(char *str){
while(*str != 0){
Send_Data(*str++);
}
}
uint16_t Read_ADC(uint8_t channel)
{
ADMUX &= 0xE0;
ADMUX = ADC_VREF_TYPE | channel;
_delay_us(10);
ADCSRA|=(1<<ADSC);
return 1;
}[/code]
من از یک کلید متصل به پایه 0 از پورت C هم استفاد می کنم. با فشردن کلید ADC درست نمونه برداری می کنه. این هم برای نشون دادن صحت عملکرد واحد ADC گذاشتم.
پ.ن. طبق کد و دیتاشیت، واحد ADC باید تقریبا هر 32 میلی ثانیه یکبار کانال 0 رو نمونه براری کنه. این زمان از زمان لازم برای نمونه برداری هم بیشتره و از این نظر مشکلی نیست.
دیدگاه