Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ATmega AVR
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/7: Рейтинг темы: голосов - 7, средняя оценка - 5.00
2 / 2 / 2
Регистрация: 05.09.2018
Сообщений: 156
1

Измерение нескольких каналов АЦП один раз за период сигнала запуска

24.11.2020, 13:22. Показов 1393. Ответов 2

Author24 — интернет-сервис помощи студентам
Всем привет!
Встал в тупик с частью программы

Работаю с АЦП. Нужно произвести последовательное измерение 11 каналов.
Сигналом запуска работы АЦП является передний фронт ШИМ-сигнала, который у меня выведен на ножку PB6. ШИМ сигнал управления реализован на 16-битном таймере 1, который выставлен в режиме Fast PWM Mode
Частота ШИМа - 300 Гц; Скважность +(-) 98%. И вот по каждому переднему фронту этого сигнала надо запускать измерение АЦП (всех каналов). Каждое АЦП должно измериться только 1 раз за период. И закончится преобразование должно не по заднему фронту ШИМа, а как можно быстрее ( минимально возможное время после переднего фронта)

Чтобы запускать АЦП по событию наступления переднего фронта, я использовал режим Auto trigger. В качестве источника (trigger source) указал Timer Overflow1, как раз тот таймер, где у меня управляющий ШИМ-сигнал.

Как я понимаю свой код:
- произошло прерывание по событию наступления переднего фронта ШИМа B;
- Программа заходит в ADC_vect и последовательно меняя MUXы, измеряет все 11 АЦП, которые мне требуются.
- выходит из прерывания и ждет следующий передний фронт.

Но тут начинаются проблемы, точнее мое непонимание:
- Как убедиться, что каждое АЦП измерилось только 1 раз?
- Как убедиться, что АЦП измерилось как можно ближе к переднему фронту, а не где-то в другом месте?
- В момент когда программа зашла в ADC_vect, она выполняет только тот код, котрый находится в прерывании, или будет реагировать на внешние сигналы?

Код прилагаю:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
 
 
#define PortInit DDRB|=(1<<7)
#define LedOn    PORTB|=(1<<7)
#define LedOff   PORTB&=~(1<<7)
 
 
 
int period=3333;
float time;
 
int ocr1a=6660; //Задаем период.
 
int ocr3b=2720;//Регулировка скважности ШИМа "А"
 
int ocr1b=100;  //Регулировка скважности ШИМа "B" 
 
 
int ocr3c;// Регулировка скважности ШИМа "D"
int t4;
 
 
volatile unsigned char adc_0;
volatile unsigned char adc_1;
volatile unsigned char adc_2;
volatile unsigned char adc_3;
volatile unsigned char adc_4;           
volatile unsigned int adc_5;    
volatile unsigned int adc_6;    
volatile unsigned int adc_7;    
volatile unsigned int adc_8;    
volatile unsigned int adc_9;    
volatile unsigned int adc_10;   
 
void UART0_Init(void) {
    UBRR0L = 103;
    UBRR0H = 0;
    UCSR0B=(1<<RXEN0)|(1<<TXEN0);
    UCSR0C=(1<<UCSZ01)|(1<<UCSZ00);
}
//Функция отправки на терминал
void uart0_tr(char value)
{
    while(!(UCSR0A & (1 << UDRE0))); // Ожидаем когда очистится буфер передачи
    UDR0 = value;   
    
}
 
 
 
//Инициализируем АЦП
void ADCInit(void) {
    ADCSRA|=(1<<ADEN);
    ADMUX=(1<<MUX2)|(1<<MUX1)|(1<<MUX0)|(1<<REFS0);         //на канал ADC7
    ADCSRA|=(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);       //делитель=128
    //ADCSRA|=(1<<ADSC);            //Запуск преобразования
    ADCSRA|=(1<<ADATE);
    ADCSRA|=(1<<ADIE);//разрешаем прерывания
    DIDR0|=(1<<ADC0D)|(1<<ADC7D);
    
}
 
unsigned int adcRead(void) {
    unsigned int adc;
    
    while(!(ADCSRA&(1<<ADIF)));
    adc=(ADCL|ADCH<<8);
    
    //ADCSRA|=(1<<ADSC);    //Начать преобразование
    ADCSRA|=(1<<ADIF);  //Сброс флага
    
    
    return adc;
}
 
 
void PWM_ini(void)
{
    
    //Задаем период таймеров
    OCR1A=ocr1a;    //меняем период таймера 1
    //ШИМ  B
    OCR1B=ocr1b;    // меняем скважность ШИМа на ножке PB6. Запуск АЦП.
    
    
    //Запускаем таймер 3 в режиме Fast PWM Mode 15
    //Сигналы A и D
    TCCR3A=(1<<COM3A1)|(1<<COM3B1)|(1<<COM3C1)|(1<<COM3C0)|(1<<WGM31)|(1<<WGM30);   //  инверсный режим для "А3" и инверсный для "B3"
    TCCR3B=(1<<WGM33)|(1<<WGM32)|(1<<CS31);     // Устанавливаем делитель=8
    
    
    
    //Запускаем таймер 1 в режиме Fast PWM Mode 15
    //Сигналы B и C
    TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0)|(1<<WGM11)|(1<<WGM10);   //  Инверсный "В"
    TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS11);     // Устанавливаем делитель=8
    //Подключаем прерывания по переполнению через TimerOverflow1
    TIMSK1=(1<<TOIE1);
    TIFR1=(1<<TOV1);
    sei();
 
}
 
void PWM_D_ini(void)
{
float konst=750;
//Freq_control();
    time=(float)ocr1a/period;
 
if (konst<adc_8)
    {
        if (t4<2570)
        {
        t4++;
        }
        else if (t4==2570)
        {
        ;
        }
        else
        {
        t4=2570;
        }
        
    }
    else if (konst>adc_8)
    {
    /*Если константа больше, чем измеренное АЦП, то нам надо уменьшить задерку t4, 
    которая для бетатрона MIB7.5 находится в пределах от 2430 до 2570 мкс.
    т.е. сначала нам надо проверить входит ли константа в установленные пределы.
    
    */
        if (t4>2430)
        {
        t4--;
        }
        else if(t4==2430)
        {
        ;
        }
        else
        {
        t4=2430;
        }
        
    }
    else if (konst==adc_8)
    {
    //Если константа равна энергии в контуре
    ;
    }
 
ocr3c=t4*time;
OCR3C=ocr3c;
 
}
 
int main(void) {
    DDRB=(1<<PORTB7)|(1<<PORTB6);
    //DDRE=(1<<PORTE5)|(1<<PORTE4)|(1<<PORTE3);
    PWM_ini();              //Инициализация ШИМ 
    UART0_Init();           //Инициализация порта на  uART
    ADCInit();              //Инициализация АЦП
    
    ADCSRA|=(1<<ADSC);
    
    
    
    while(1) {
    
    
        
    }
}
 
ISR(TIMER1_OVF_vect)
{
//uart0_tr(thermo_1);
//uart0_tr(thermo_2);
 
}
 
ISR(ADC_vect)
{
//uint8_t theLOW=ADCL;
//uint16_t ADC_ten_bits=ADCH<<8|theLOW;
 
/*
Отрывок из Datasheet,стр.286:
When ADCL is read, the ADC Data Register is not updated until ADCH is read. Consequently, if the result is left
adjusted and no more than 8-bit precision (7 bit + sign bit for differential input channels) is required, it is sufficient to
read ADCH. Otherwise, ADCL must be read first, then ADCH.
Поэтому, для 8-битных значений мы читаем именно старший байт
*/
//ADC0_8bit
if(ADMUX==0b01100000)
    {
    
    
        adc_0=ADCH;
        uart0_tr(adc_0);
        ADMUX=0b01100001;
    }   
//ADC1_8bit
else if(ADMUX==0b01100001)
    {
        
        adc_1=ADCH;
        uart0_tr(adc_1);
        ADMUX=0b01100010;
        ADCSRA|=(1<<ADSC);
    }
//ADC2_8bit
else if(ADMUX==0b01100010)
    {
        adc_2=ADCH;
        
        
        ADMUX=0b01100011;
        ADCSRA|=(1<<ADSC);
    }
    
//ADC3_thermo_4_8_bit
else if(ADMUX==0b01100011)
    {
        
        adc_3=ADCH; 
        //uart0_tr(thermo_4);
        ADMUX=0b01100100;
        ADCSRA|=(1<<ADSC);
    }
    
//ADC4_8_bit
else if(ADMUX==0b01100100)
    {
        
        adc_4=ADCH;
        ADMUX=0b01000101;
        ADCSRA|=(1<<ADSC);
    }
    
//ADC5_10_bit
else if(ADMUX==0b01000101)
    {
        
        adc_5=ADCH;
        ADMUX=0b01000110;
        ADCSRA|=(1<<ADSC);
    }
    
    
//ADC6_power_doza_min_10_bit
else if(ADMUX==0b01000110)
    {
        adc_6=ADC;      
        ADMUX=0b01000111;
        ADCSRA|=(1<<ADSC);
        
    }
    
//7ADC_10_bit
else if(ADMUX==0b01000111)
    {
        
        adc_7=ADC;
        ADCSRB=0b00001110;
        ADMUX=0b01000000;
        ADCSRA|=(1<<ADSC);
    }
    
    
// Включаем MUX5    
//ADC8_10_bits
else if(ADMUX==0b01000000&&ADCSRB==0b00001110)
    {
    
        
        adc_8=ADC;
        ADCSRB=0b00001110;
        ADMUX=0b01000001;
        ADCSRA|=(1<<ADSC);
    }
 
//ADC9_10_bits
else if(ADMUX==0b01000001&&ADCSRB==0b00001110)
    {
        adc_9=ADC;
        ADCSRB=0b00001110;
        ADMUX=0b01000010;
        ADCSRA|=(1<<ADSC);
    }
 
//ADC10_10_bits
else if(ADMUX==0b01000010&&ADCSRB==0b00001110)
    {
        adc_10=ADC;
        ADCSRB=0b00000110;
        ADMUX=0b01100000;
        ADCSRA|=(1<<ADSC);
    }
    
 
 
}
Очень буду благодарен за советы
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.11.2020, 13:22
Ответы с готовыми решениями:

измерение частоты сигнала с помощью ацп
Здравствуйте! Есть сигнал условно периодический (изменение периода составляет +- 10мс ) и...

Использование нескольких каналов АЦП
Всем привет. Пишу небольшую прогу для ATmega8, и возник вопрос как считывать данные сразу с двух...

AVR АЦП использование нескольких каналов
Кто пробовал использовать несколько каналов АЦП одновременно (ну, почти одновременно) - как это...

Опрос нескольких регулярных каналов АЦП STM32F100
Всем привет! Проблема с опросом нескольких регулярных каналов АЦП STM32F100 (Отл плата STM32F100VL...

2
1176 / 653 / 111
Регистрация: 15.05.2012
Сообщений: 4,015
25.11.2020, 08:11 2
Цитата Сообщение от iaz5 Посмотреть сообщение
- Как убедиться, что каждое АЦП измерилось только 1 раз?
Однократный запуск спасет отца русской революции.
Цитата Сообщение от iaz5 Посмотреть сообщение
- Как убедиться, что АЦП измерилось как можно ближе
Смотрим даташит. Видим, что измерение происходит за 12 тактов процессора.
Цитата Сообщение от iaz5 Посмотреть сообщение
только тот код, котрый находится в прерывании
При входе в прерывание автоматом сбрасывается бит общего разрешения прерываний. Пока его насильно не взвести или не придет команда RETI, процессору глубоко наплевать, что происходит снаружи.
0
3881 / 2479 / 418
Регистрация: 09.09.2017
Сообщений: 10,889
25.11.2020, 11:01 3
Цитата Сообщение от pyzhman Посмотреть сообщение
Смотрим даташит. Видим, что измерение происходит за 12 тактов процессора.
Вроде ж 12,5 тактов. Или 25 если измерение первое.
0
25.11.2020, 11:01
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.11.2020, 11:01
Помогаю со студенческими работами здесь

Измерение значения АЦП при регистрации переднего фронта ШИМ-сигнала
Всем привет! Пытаюсь запустить АЦП по переднему фронту ШИМ-сигнала. ШИМ настроен на ножку PE5....

Считывание аналогового сигнала с нескольких каналов ATmega328
Добрый день. Начал разработку регулятора напряжения, на основании имеющейся схемы. Столкнулся с...

Один период сигнала
t1 = 0:2*pi/100:2*pi-2*pi/100; Meander1 = square(t1,22); % один период сигнала. % Выполним...

Объединение нескольких Internet каналов в один
Подскажите пожалуйста каким сетевым устройством возможно объеденить три ADSL канала по 2мбт каждый...

Два сигнала АЦП на один ЖКИ
Помогите пожалуйста. Есть два сигнала напряжения подключенные к AN0 и AN1 PIC16F877. Не...

во сколько раз уменьшится U_c за один период
Помогите пожалуйста!!! Дан колебательный контур из последовательно соединенных R, L, C. Найти: во...

Сколько раз за один период гармонического колебания потенциальная энергия будет равна кинетической
Добрый день. Подскажите, сколько раз за один период гармонического колебания потенциальная энергия...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru