АЦП+Usart

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

АЦП+Usart

Сообщение pokk »

Моделирую в протеусе ситуация на вход подаю гармонический сигнал и дальше по уарту передаю в терминал а от туда в exel и смотрю что получилось =))

но работает это всё как-то очень плохо одни раз всего по случайности получилось что-то похожее на синусоиду (положительная полу волна) а дальше пошло что-то на подобии треугольных импульсов а чаше всего вверху много точек около пикового значения а дальше их нету

в общем всё идёт на прерывании как на цап приходит сигнал он полученное значение записывает в массив а дальше возникает прерывание по опустошению регистра UDR и и там соответственно из этого массива передаю в терминал

подскажите почему у меня такой не ровный сигнал получается ?

не нравится что приходится через массив передавать можно как-нибудь по другому ?
как правильно сделать передачу ?

если вместо b[index]=ADCH; писать b[index]=ADCL; то протеус начинает ругаться что регистр ADC заблокирован и он не может из него считать с чем это может быть связано ? ставил задержки не помогло =(

Код: Выделить всё


#include <mega16.h>

// Standard Input/Output functions
#include <stdio.h>

#include <delay.h>

unsigned char index;



unsigned char bufL;
unsigned char bufH;
unsigned char varr;
char b[256];

#define ADC_VREF_TYPE 0x00

#define FOSC 8000000// Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1
#define RXEN 4
#define TXEN 3
#define URSEL 7
#define USBS 3
#define UCSZ0 1
#define UDRE 5
#define UDRIE 5

#define ADEN   7
#define ADSC   6
#define ADFR  5
#define ADIF  4
#define ADIE  3
#define ADPS2  2
#define ADPS1  1
#define ADPS0  0

void USART_Init( unsigned int ubrr)
{
/* Set baud rate */
UBRRH = (unsigned char)(ubrr>>8);
UBRRL = (unsigned char)ubrr;
/* Enable receiver and transmitter */
UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<UDRIE);
/* Set frame format: 8data, 2stop bit */
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}  
interrupt[USART_DRE] void USART_transmit(void)
{
        UDR=b[varr];   
         varr++ ;
 if (varr>250){varr=0;}
         
}   

interrupt[ADC_INT] void ADC_result(void)
{
       b[index]=ADCH;
        index++;     
if (index>250){index=0;}      
}
// Declare your global variables here
void main(void)
{
// Declare your local variables here
PORTB=0x00;
DDRB=0xFF;

USART_Init ( MYUBRR );
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

ADMUX=224; // 1110000 (внутрений источник опороного напряжения выравнивание по левой границе)
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0)|(1<<ADSC)|(1<<ADFR)|(1<<ADIE)|(1<<ADIF); 
        
#asm("sei");
while (1)
      {

      };
}

Реклама
Аватара пользователя
Engineer_Keen
Друг Кота
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Re: АЦП+Usart

Сообщение Engineer_Keen »

pokk писал(а): если вместо b[index]=ADCH; писать b[index]=ADCL; то протеус начинает ругаться что регистр ADC заблокирован и он не может из него считать с чем это может быть связано ? ставил задержки не помогло =(
ADCH нужно читать до ADCL, даже если его значение не нужно. Таковы правила работы с 16-битными регистрами в AVR.
Реклама
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Re: АЦП+Usart

Сообщение pokk »

ADCH нужно читать до ADCL, даже если его значение не нужно. Таковы правила работы с 16-битными регистрами в AVR.
Ясно спасибо.

Кварц на 2Мгц стоит коэффициент предделителя ацп 64 и 128 ставил
что-то совсем не понятное происходит 2Мгц/128=15.5кгц

на вход подаю гармонический сигнал с частотой 1кгц это в 15 раз меньше частоты дискретизации при такой частоте сигнал должен быть нормальный приходить а мне передаётся всего 3 значения в одной полу волне =(

при 1 гц вот что получается
Изображение
почему на 500 и 1000 так прыгает ?
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Re: АЦП+Usart

Сообщение pokk »

в общем теперь заработало всё но почему оно работает и как не понятно :))

сделал следующее выбрал режим работы ацп по прерыванию по таймеру при Совпадение таймера/счетчика Т1
Выставил частоту 250,000 kHz и коэффициент деления 40000 (OCR1AH=0x9c; OCR1AL=0x40;)
т.е он с частотой в 25000Гц будет считать до 40000 и это получается за 0.16 секунд он досчитает и получается ацп будет включается через это время ? (как -то медленно)

далее я подавал гармонические сигналы с частотами 600 800 1600 2500 гц
и получал количество точек в периоде для 2500 - 100 точек для 800-310 1600- 156
в общем получается если частоту 250000гц делить на количество точек то выходит частоты входного сигнала.Так вот каким образом коэффициент деления(40000) здесь участвует ? он явно влияет на скорость
если там его уменьшать до 250-4000 то в периоде 3-6 точек и там плохо похоже на синусоиду.

Код: Выделить всё

/*****************************************************
Chip type               : ATmega16
Program type            : Application
AVR Core Clock frequency: 2,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*****************************************************/
#include <mega16.h>
#include <m8_128.h>
#include <usart.c>
// Standard Input/Output functions
#include <stdio.h>
#include <delay.h>

// Timer 1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
// Place your code here
}

interrupt[ADC_INT] void ADC_result(void)
{
USART_PutChar(ADCH);
if (USART_GetTxCount()>20){USART_FlushTxBuf();}
 
}
// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPB] void timer1_compa_isr(void)
{

}
// Declare your global variables here
void main(void)
{
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 250,000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: On
TCCR1A=0x00;
TCCR1B=0x0A;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;

OCR1AH=0x9c;       //40000
OCR1AL=0x40;

OCR1BH=0x00;
OCR1BL=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x0C;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

ADMUX=224; // 1110000 (внутрений источник опороного напряжения выравнивание по левой границе)
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADSC)|(1<<ADFR)|(1<<ADIE)|(1<<ADIF);
SFIOR= (1<<ADTS2)|(0<<ADTS1)|(1<<ADTS0); //Прерывание по событию "Совпадение" таймера/счетчика Т1

USART_Init();
// Global enable interrupts
#asm("sei")

while (1)
      {
      // Place your code here

      };
}

Код: Выделить всё

//помещает символ в буфер, инициирует начало передачи
void USART_PutChar(unsigned char sym)
{
  //если модуль usart свободен и это первый символ
  //пишем его прямо в регистр UDR
  if(((UCSRA & (1<<UDRE)) != 0) && (txCount == 0)) UDR = sym;
  else {
    if (txCount < SIZE_BUF){    //если в буфере еще есть место
      usartTxBuf[txBufTail] = sym; //помещаем в него символ
      txCount++;                   //инкрементируем счетчик символов
      txBufTail++;                 //и индекс хвоста буфера
      if (txBufTail == SIZE_BUF) txBufTail = 0;
    }
  }
}
1.rar
(70.3 КБ) 134 скачивания
Реклама
Эиком - электронные компоненты и радиодетали
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Re: АЦП+Usart

Сообщение pokk »

Ни у кого ни каких мыслей нету ?
Реклама
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»