Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/29: Рейтинг темы: голосов - 29, средняя оценка - 4.86
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511

Передача данных от АЦП по USART

09.09.2019, 14:45. Показов 6419. Ответов 16

Студворк — интернет-сервис помощи студентам
Здравствуйте, есть задача: оцифровывать аналоговый сигнал на нескольких ножках МК (stm32f411) и полученный результат отправлять в ПК по USART, все это должно выполняться циклично примерно раз в 500 млсек. Настроил ADC, DMA, так же выполнил настройку USART. Но не получается отправить данные. Т.е. АЦП оцифровывает сигнал с 5 ножек, записывает данные в буфер, но полученные буфер не получается отправить (данные АЦП - 12 битные), USART настроен на передачу 8 бит.

Код:

main.c

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
// ADC, DMA, USART
 
#include "main.h"
 
//------------------------------------------------------------------
// Includes
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32F4xx_adc.h"
#include "stm32f4xx_dma.h"
 
#include "stm32f4xx_exti.h"
#include "misc.h"
//------------------------------------------------------------------
 
 
//------------------------------------------------------------------
// Variables
#define LED_PORT GPIOD
#define LED_3_PIN GPIO_Pin_13
#define LED_4_PIN GPIO_Pin_12
#define LED_5_PIN GPIO_Pin_14
#define LED_6_PIN GPIO_Pin_15
 
__IO uint16_t ADC1ConvertedValue[5];  
__IO uint32_t ADC1DisplayedValue;
uint8_t data = 0;
//------------------------------------------------------------------
 
 
//------------------------------------------------------------------
void SendStrtoPC(char* ADC1ConvertedValue_p, uint16_t count)
{
        uint16_t i=0;
        
        while(i < count)
        {
            while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET){}
            USART_SendData(USART2, ADC1ConvertedValue_p[i]);
            i++;
        }
}
//------------------------------------------------------------------
 
 
//------------------------------------------------------------------
// Interrupt of DMA function
void DMA2_Stream0_IRQHandler (void)
{
 
//  SendStrtoPC(ADC1ConvertedValue, 5); 
    USART_SendData(USART2, data++);
    DWT_Delay_ms(500);
    
//   ADC1ConvertedVoltage = ADC1ConvertedValue *3300/0xFFF;
 
//         if  (ADC1ConvertedVoltage < 825)
//            {
//            GPIO_SetBits(LED_PORT, LED_6_PIN);
//            GPIO_ResetBits(LED_PORT, LED_4_PIN);
//            GPIO_ResetBits(LED_PORT, LED_3_PIN);
//            GPIO_ResetBits(LED_PORT, LED_5_PIN);
//            } else
//               {
//               if  (ADC1ConvertedVoltage <= 1650)
//                  {
//                     GPIO_SetBits(LED_PORT, LED_6_PIN);
//                     GPIO_SetBits(LED_PORT, LED_4_PIN);
//                     GPIO_ResetBits(LED_PORT, LED_3_PIN);
//                     GPIO_ResetBits(LED_PORT, LED_5_PIN);
//                  } else
//                     {
//                     if  (ADC1ConvertedVoltage <= 2475)
//                        {
//                        GPIO_SetBits(LED_PORT, LED_6_PIN);
//                        GPIO_SetBits(LED_PORT, LED_4_PIN);
//                        GPIO_SetBits(LED_PORT, LED_3_PIN);
//                        GPIO_ResetBits(LED_PORT, LED_5_PIN);
//                        } else
//                           {
//                           if  (ADC1ConvertedVoltage <= 3300)
//                              {
//                              GPIO_SetBits(LED_PORT, LED_6_PIN);
//                              GPIO_SetBits(LED_PORT, LED_4_PIN);
//                              GPIO_SetBits(LED_PORT, LED_3_PIN);
//                              GPIO_SetBits(LED_PORT, LED_5_PIN);
//                              } else
//                                 {
//                                 GPIO_ResetBits(LED_PORT, LED_6_PIN);
//                                 GPIO_ResetBits(LED_PORT, LED_4_PIN);
//                                 GPIO_ResetBits(LED_PORT, LED_3_PIN);
//                                 GPIO_ResetBits(LED_PORT, LED_5_PIN);
//                                 }
//                           }
//                     }
//               }
}
//------------------------------------------------------------------
 
 
//------------------------------------------------------------------------------------------------------------------------
int main(void) 
{
        
    USART2_ini();
    
//------------------------------------------------------------------------------------------------------------------------
// Delay definition
//
    DWT_DelayUpdate();
    DWT_Init();
    uint32_t DWT_GetTick(void);
    void DWT_Delay_sec(uint32_t sec);
    void DWT_Delay_ms(uint32_t ms);
    void DWT_Delay_us(uint32_t us);
    uint8_t DWT_Test_sec(uint32_t start, uint32_t time);
    uint8_t DWT_Test_ms(uint32_t start, uint32_t time);
    uint8_t DWT_Test_us(uint32_t start, uint32_t time);
    uint32_t DWT_Time_sec(uint32_t start, uint32_t current);
    uint32_t DWT_Time_ms(uint32_t start, uint32_t current);
    uint32_t DWT_Time_us(uint32_t start, uint32_t current);
//------------------------------------------------------------------------------------------------------------------------
 
 
//------------------------------------------------------------------
// RCC
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOC, ENABLE); //RCC_AHB1Periph_GPIOC
//------------------------------------------------------------------
 
 
//------------------------------------------------------------------
// DMA
  DMA_InitTypeDef DMA_InitStructure;
   DMA_InitStructure.DMA_Channel = DMA_Channel_0;
   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &ADC1->DR;                                                                           
//   DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue;
     DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue[0];
   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
//   DMA_InitStructure.DMA_BufferSize = 1;
     DMA_InitStructure.DMA_BufferSize = 5;
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
//   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
   DMA_InitStructure.DMA_Priority = DMA_Priority_High;
   DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
   DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
   DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
   DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
   DMA_Init(DMA2_Stream0, &DMA_InitStructure);
  DMA_Cmd(DMA2_Stream0, ENABLE);
    DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
//------------------------------------------------------------------
 
 
//------------------------------------------------------------------
// GPIOs 
     GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
   GPIO_Init(GPIOA, &GPIO_InitStructure);
     
     GPIO_InitTypeDef GPIO_InitStructure2;                                               //
    GPIO_InitStructure2.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_5;  //
    GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_AN;                                      //
    GPIO_InitStructure2.GPIO_PuPd = GPIO_PuPd_NOPULL ;                                 //
   GPIO_Init(GPIOC, &GPIO_InitStructure2);                                             //
  
   GPIO_InitTypeDef ledinit;
        ledinit.GPIO_Mode = GPIO_Mode_OUT;
        ledinit.GPIO_OType = GPIO_OType_PP;
        ledinit.GPIO_PuPd = GPIO_PuPd_NOPULL;
        ledinit.GPIO_Speed = GPIO_Speed_2MHz;
        ledinit.GPIO_Pin = LED_3_PIN | LED_4_PIN  | LED_5_PIN | LED_6_PIN;
   GPIO_Init(LED_PORT, &ledinit);
//------------------------------------------------------------------
 
 
//------------------------------------------------------------------
// ADC
   ADC_CommonInitTypeDef ADC_CommonInitStruct;
      ADC_CommonInitStruct.ADC_Mode = ADC_Mode_Independent;
      ADC_CommonInitStruct.ADC_Prescaler = ADC_Prescaler_Div2;
      ADC_CommonInitStruct.ADC_DMAAccessMode =  ADC_DMAAccessMode_Disabled;
      ADC_CommonInitStruct.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
   ADC_CommonInit(&ADC_CommonInitStruct);
 
   ADC_InitTypeDef ADC_InitStruct;
      ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;
//      ADC_InitStruct.ADC_ScanConvMode = DISABLE;
      ADC_InitStruct.ADC_ScanConvMode = ENABLE;
      ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;
      ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
      ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
      ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
//      ADC_InitStruct.ADC_NbrOfConversion = 1;
          ADC_InitStruct.ADC_NbrOfConversion = 5;
   ADC_Init(ADC1,&ADC_InitStruct);
 
//   ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_3Cycles);
     ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_3Cycles);
     ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_3Cycles);
     ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_3Cycles);
     ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 4, ADC_SampleTime_3Cycles);
     ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 5, ADC_SampleTime_3Cycles);
 
   ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
//------------------------------------------------------------------
 
 
//------------------------------------------------------------------
// Interrupt of DMA
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = DMA2_Stream0_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 5;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 5;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
 
    NVIC_EnableIRQ (DMA2_Stream0_IRQn);
//------------------------------------------------------------------
 
 
//------------------------------------------------------------------
// Enable
   ADC_DMACmd(ADC1, ENABLE);
   ADC_Cmd(ADC1, ENABLE);
   ADC_SoftwareStartConv(ADC1);
//------------------------------------------------------------------
 
 
    while(1)
    {
//------------------------------------------------------------------        
 
//------------------------------------------------------------------
        
//      DWT_Delay_ms(1000);
//      ADC_SoftwareStartConv(ADC1);               // Regular               
    }
 
}
//------------------------------------------------------------------------------------------------------------------------
USART.c

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
//------------------ SETTING THE USART INTERFACE -------------------------
 
#include "USART.h"
 
//------------------------------------------------------------------------------------------------------------------------
//--------------------- USART Function -------------------
//
void USART2_ini(void)
{
    
    // Pins configyration:
    // TX - PA2
    // RX - PA3
    // GND - GND
    
    // Setting the pins 
    GPIO_InitTypeDef GPIO_Init_USART;
    USART_InitTypeDef USART_InitUser;
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    
    GPIO_Init_USART.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
    GPIO_Init_USART.GPIO_Mode = GPIO_Mode_AF;
    GPIO_Init_USART.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init_USART.GPIO_OType = GPIO_OType_PP;
    GPIO_Init_USART.GPIO_PuPd = GPIO_PuPd_UP;
    
    GPIO_Init(GPIOA, &GPIO_Init_USART);
    
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
    
    // Setting the USART2
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    
    USART_InitUser.USART_BaudRate=9600;
    USART_InitUser.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
    USART_InitUser.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
    USART_InitUser.USART_Parity=USART_Parity_No;
    USART_InitUser.USART_StopBits=USART_StopBits_1;
    USART_InitUser.USART_WordLength=USART_WordLength_8b;
    
    USART_Init(USART2, &USART_InitUser);
    
    USART_Cmd(USART2, ENABLE);
    
}
 
//------------------------------------------------------------------------------------------------------------------------
В приведенном коде передачу данных по USART хочу осуществить в функции
C
1
void DMA2_Stream0_IRQHandler (void)
- прерывании по окончанию работы DMA. В отладчике проверил, буфер заполняется корректно, однако данные по USART не передаются.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
09.09.2019, 14:45
Ответы с готовыми решениями:

Передача данных с АЦП по USART
Здравствуйте уважаемые форумчане подскажите пожалуйста я взял рабочий код по работе АЦП и DMA настроил USORT. DMA берет значения АЦП...

передача данных с 2 портов can и 1 usart в usart
Доброго времени суток форумчане! Пытаюсь написать код для stm32f4disko с помощью которого можно читать данные с 2 can и usart. насколько я...

передача данных USART + DMA и непонятные иероглифы
Всем привет! Есть проблема с передачей данных с МК на ПК через USORT + DMA. Ранее все работало отлично, но с какого-то момента, а...

16
Эксперт по электронике
6582 / 3209 / 335
Регистрация: 28.10.2011
Сообщений: 12,518
Записей в блоге: 7
09.09.2019, 15:24
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
полученные буфер не получается отправить (данные АЦП - 12 битные), USART настроен на передачу 8 бит.
Данные в переменных типа uint16_t. Разделите переменную на две uint8_t и передавайте.


Цитата Сообщение от DmitryDDDD Посмотреть сообщение
C
1
2
3
4
5
6
// Interrupt of DMA function
void DMA2_Stream0_IRQHandler(void) // <-- !!!!!!!!!!!!!!!!
{
//  SendStrtoPC(ADC1ConvertedValue, 5); 
    USART_SendData(USART2, data++);
    DWT_Delay_ms(500); // <-- !!!!!!!!!!!!!!!!
Желаю удачи в разработке!
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
09.09.2019, 15:29
DmitryDDDD, Ай яй яй, так делать в прерывании
C
1
DWT_Delay_ms(500);
Обработчики прерываний - зашел, вышел. Ставь там флаг и отрабатывай его в основном цикле. Это раз.
Два. Так у вас отправится только младший байт измерений, учитывая что оцифровка производится в режиме 12 бит.
C
1
USART_SendData(USART2, ADC1ConvertedValue_p[i]);
Три. Флаг прерывания DMA надо сбрасывать в прерывании.

Как лучше сделать вашу систему:
1) Настраиваем запуск АЦП по триггеру от таймера (смотрим таблицу триггеров в RM). И настраиваем этот таймер на 500 мс
2) Настраиваем DMA на запись в массив (у вас уже сделано).
3) В прерывании DMA выставляем флаг готовности к отправке. И чистим флаг прерывания.
4) В осовно цикле опрашиваем флаг готовности к отправке -> если 1 то отправляем, и сбрасываем в 0.
При желании отправку можно тоже по DMA сделать.
0
Эксперт по электронике
6582 / 3209 / 335
Регистрация: 28.10.2011
Сообщений: 12,518
Записей в блоге: 7
09.09.2019, 15:44
Цитата Сообщение от _SayHello Посмотреть сообщение
у вас отправится только младший байт измерений
На самом деле отправляется данные 2.5 каналов. DMA буфер __IO uint16_t ADC1ConvertedValue[5]; В функции передачи указатель на массив преобразуется в char* (в МК должен быть эквивалентен uint8_t*) и отправляется через USART. Но т. к. массив имеет размер 10 байт, а отправляется только 5, получается 2.5 канала, как бы странно это не звучало.

Цитата Сообщение от _SayHello Посмотреть сообщение
При желании отправку можно тоже по DMA сделать.
Если есть свободный канал лучше так поступить. Тогда можно в прерывании DMA от АЦП, сразу же отправить через DMA+USART.
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
09.09.2019, 16:23
locm,
Цитата Сообщение от locm Посмотреть сообщение
а самом деле отправляется данные 2.5 каналов. DMA буфер __IO uint16_t ADC1ConvertedValue[5]; В функции передачи указатель на массив преобразуется в char* (в МК должен быть эквивалентен uint8_t*) и отправляется через USART. Но т. к. массив имеет размер 10 байт, а отправляется только 5, получается 2.5 канала, как бы странно это не звучало.
Это правда. Странно это не звучит, а наоборот логично.
В целом в коде каша намешана.
DmitryDDDD, вы перед тем как проектировать устройство, (как бы это просто не звучало) карандашиком "архитектуру" нарисуйте, а то у Вас получается все свалено в кучу.

В чем выражается проблема? ДАнные приходят некорректные или они не идут вообще?
Если первый вариант, то locm, вам объяснил.
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
11.09.2019, 13:36  [ТС]
Всем спасибо за советы, почитал еще информацию, изменил код:

1) Подключение библиотек и создание буфера под данные
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// ADC, DMA, USART
 
#include "main.h"
 
//------------------------------------------------------------------
// Includes
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32F4xx_adc.h"
#include "stm32f4xx_dma.h"
 
#include "stm32f4xx_exti.h"
#include "misc.h"
//------------------------------------------------------------------
 
 
//------------------------------------------------------------------
uint8_t ADC_buffer[8];
//------------------------------------------------------------------

2) Прерывание по DMA
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
//------------------------------------------------------------------
// Interrupt of DMA function
void DMA2_Stream0_IRQHandler(void)
{
    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
    USART_GetFlagStatus(USART2, USART_FLAG_TXE);
}
//------------------------------------------------------------------

3)Отправка данных в ПК
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
//------------------------------------------------------------------
void SendStrtoPC(uint8_t* ADC_buffer_p, uint8_t count)
{
        uint8_t i=0;
        
        while(i < count)
        {
            while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET){}
            USART_SendData(USART2, ADC_buffer_p[i]);
            i++;
        }
}
//------------------------------------------------------------------

4) Настройка таймера
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//------------------------------------------------------------------
void Timer_ADC (void)
{
// If HCLK = 100 MHz, then frequency of APB1 timer clocks = 100 MHz, 
// Prescaler = 50000, Period = 1000, T = 500 msec
    TIM_TimeBaseInitTypeDef TIM_Time_user;
        
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    
    TIM_Time_user.TIM_Prescaler = 50000-1;
    TIM_Time_user.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_Time_user.TIM_Period = 1000;
    TIM_Time_user.TIM_ClockDivision = TIM_CKD_DIV1;
    
    TIM_TimeBaseInit(TIM3, &TIM_Time_user);
            
    TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);
    TIM_Cmd(TIM3, ENABLE);
}
//------------------------------------------------------------------

5) Настройка АЦП и ДМА
Кликните здесь для просмотра всего текста
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
//------------------------------------------------------------------
void GPIO_ini (void)
{
     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC, ENABLE); 
 
     GPIO_InitTypeDef GPIO_InitStructureA;                                               
    GPIO_InitStructureA.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;  
    GPIO_InitStructureA.GPIO_Mode = GPIO_Mode_AN;                                      
    GPIO_InitStructureA.GPIO_PuPd = GPIO_PuPd_NOPULL ;                                 
   GPIO_Init(GPIOA, &GPIO_InitStructureA); 
 
     GPIO_InitTypeDef GPIO_InitStructureC;                                               
    GPIO_InitStructureC.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_5;  
    GPIO_InitStructureC.GPIO_Mode = GPIO_Mode_AN;                                      
    GPIO_InitStructureC.GPIO_PuPd = GPIO_PuPd_NOPULL ;                                 
   GPIO_Init(GPIOC, &GPIO_InitStructureC); 
}
//------------------------------------------------------------------
 
 
//------------------------------------------------------------------
void ADC_ini (void)
{
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    
   ADC_InitTypeDef ADC_Init_user;   
        ADC_Init_user.ADC_Resolution = ADC_Resolution_8b;
        ADC_Init_user.ADC_ScanConvMode = ENABLE;
        ADC_Init_user.ADC_ContinuousConvMode = DISABLE;
        ADC_Init_user.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
        ADC_Init_user.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;
        ADC_Init_user.ADC_DataAlign = ADC_DataAlign_Right;
        ADC_Init_user.ADC_NbrOfConversion = 8;              
     ADC_Init(ADC1, &ADC_Init_user);
     
      ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_15Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 2, ADC_SampleTime_15Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 3, ADC_SampleTime_15Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 4, ADC_SampleTime_15Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 5, ADC_SampleTime_15Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 6, ADC_SampleTime_15Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 7, ADC_SampleTime_15Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 8, ADC_SampleTime_15Cycles);
 
    NVIC_EnableIRQ(ADC_IRQn);   
    
    ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); 
 
    ADC_Cmd(ADC1, ENABLE);
}
//------------------------------------------------------------------
 
 
//------------------------------------------------------------------
void DMA_ADC (void)
{
     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
     
     DMA_InitTypeDef DMA_ini_ADC;
         DMA_ini_ADC.DMA_Channel = DMA_Channel_0;
         DMA_ini_ADC.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR);
         DMA_ini_ADC.DMA_Memory0BaseAddr = (uint32_t)ADC_buffer;
         DMA_ini_ADC.DMA_DIR = DMA_DIR_PeripheralToMemory;
         DMA_ini_ADC.DMA_BufferSize = sizeof(ADC_buffer);
         DMA_ini_ADC.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
         DMA_ini_ADC.DMA_MemoryInc = DMA_MemoryInc_Enable;
         DMA_ini_ADC.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
         DMA_ini_ADC.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
         DMA_ini_ADC.DMA_Mode = DMA_Mode_Circular;
         DMA_ini_ADC.DMA_Priority = DMA_Priority_High;
       DMA_ini_ADC.DMA_FIFOMode = DMA_FIFOMode_Disable;
       DMA_ini_ADC.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
         DMA_ini_ADC.DMA_MemoryBurst = DMA_MemoryBurst_Single;
         DMA_ini_ADC.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;  
     DMA_Init(DMA2_Stream0, &DMA_ini_ADC);
    
     ADC_DMACmd(ADC1, ENABLE);   
     ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
    
   NVIC_EnableIRQ (DMA2_Stream0_IRQn); 
     DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
     
     DMA_Cmd(DMA2_Stream0, ENABLE);
 }
//------------------------------------------------------------------

6) int main
Кликните здесь для просмотра всего текста
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
//------------------------------------------------------------------------------------------------------------------------
int main(void) 
{
//------------------------------------------------------------------
// Initialization
//  
    USART2_ini();
    Timer_ADC();
    GPIO_ini();
    ADC_ini();
    DMA_ADC();
//------------------------------------------------------------------
    
    
//------------------------------------------------------------------
// Delay definition
//
    DWT_DelayUpdate();
    DWT_Init();
    uint32_t DWT_GetTick(void);
    void DWT_Delay_sec(uint32_t sec);
    void DWT_Delay_ms(uint32_t ms);
    void DWT_Delay_us(uint32_t us);
    uint8_t DWT_Test_sec(uint32_t start, uint32_t time);
    uint8_t DWT_Test_ms(uint32_t start, uint32_t time);
    uint8_t DWT_Test_us(uint32_t start, uint32_t time);
    uint32_t DWT_Time_sec(uint32_t start, uint32_t current);
    uint32_t DWT_Time_ms(uint32_t start, uint32_t current);
    uint32_t DWT_Time_us(uint32_t start, uint32_t current);
//------------------------------------------------------------------
 
 
    while(1)
    {
//------------------------------------------------------------------        
        if (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == SET)
        {
            USART_ClearFlag(USART2, USART_FLAG_TXE);
            SendStrtoPC(ADC_buffer, 8);
            DWT_Delay_ms(50);
        }
        else {}
//------------------------------------------------------------------                
    }
 
}
//------------------------------------------------------------------------------------------------------------------------

В режиме отладки данные заполняются в буфер корректно, однако по USART в ПК приходят все нули. Для упрощения решил пока работать только с 8 битными данными. Не уверен на счет правильности выставления и очистки флагов DMA и USART. Причем данные в ПК приходят не раз в 500 млсек, как настроен таймер, а просто несколько пакетов и передача останавливается. В чем может быть проблема?

Добавлено через 30 минут
_SayHello , locm, Если перекидывать из буфера в USART данные при помощи DMA, можно использовать тот же DMA только другой канал или необходимо настраивать другой DMA?
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
11.09.2019, 14:11
Лучший ответ Сообщение было отмечено DmitryDDDD как решение

Решение

DmitryDDDD,
сделай так:
C
1
2
3
4
5
void DMA2_Stream0_IRQHandler(void)
{
    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
    readyToTransmitFlag = 1;
}
C
1
2
3
4
5
6
7
8
9
10
11
void SendStrtoPC(uint8_t* ADC_buffer_p, uint8_t count)
{
        uint8_t i=0;
        
        while(i < count)
        {
            while(!USART_GetFlagStatus(USART2, USART_FLAG_TXE));
            USART_SendData(USART2, ADC_buffer_p[i]);
            i++;
        }
}
В main:
C
1
2
3
4
5
6
7
8
9
    while(1)
    {  
        if (readyToTransmitFlag)
        {
            SendStrtoPC(ADC_buffer, 8);
            readyToTransmitFlag = 0;
        }
      
    }
Добавлено через 1 минуту
DmitryDDDD, Период поправьте еще:
C
1
TIM_Time_user.TIM_Period = 1000 - 1;
Добавлено через 1 минуту
DmitryDDDD,
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
Если перекидывать из буфера в USART данные при помощи DMA, можно использовать тот же DMA только другой канал или необходимо настраивать другой DMA?
можно канал того же DMA использовать, тут каналы все равно друг за другом отрабатывать будут, поэтому особо их арбитраж не важен
1
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
11.09.2019, 14:18  [ТС]
_SayHello, изменил код, буфер так же заполняется, данные перестали отправляться

readyToTransmitFlag объявил как uint8_t, в цикле while так же пробовал изменять условие на if (readyToTransmitFlag == 1)
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
11.09.2019, 14:23
DmitryDDDD, Настройку USART скиньте текущую. Что отладчик говорит?
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
11.09.2019, 14:25  [ТС]
_SayHello
Настройка USART
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
void USART2_ini(void)
{
    
    // Pins configyration:
    // TX - PA2
    // RX - PA3
    // GND - GND
    
    // Setting the pins 
    GPIO_InitTypeDef GPIO_Init_USART;
    USART_InitTypeDef USART_InitUser;
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    
    GPIO_Init_USART.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
    GPIO_Init_USART.GPIO_Mode = GPIO_Mode_AF;
    GPIO_Init_USART.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init_USART.GPIO_OType = GPIO_OType_PP;
    GPIO_Init_USART.GPIO_PuPd = GPIO_PuPd_UP;
    
    GPIO_Init(GPIOA, &GPIO_Init_USART);
    
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
    
    // Setting the USART2
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    
    USART_InitUser.USART_BaudRate=9600;
    USART_InitUser.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
    USART_InitUser.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
    USART_InitUser.USART_Parity=USART_Parity_No;
    USART_InitUser.USART_StopBits=USART_StopBits_1;
    USART_InitUser.USART_WordLength=USART_WordLength_8b;
    
    USART_Init(USART2, &USART_InitUser);
    
    USART_Cmd(USART2, ENABLE);
    
}
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
11.09.2019, 14:29  [ТС]
В цикле while отладчик не попадаетт в условие if, только проверяет его бесконечно
Миниатюры
Передача данных от АЦП по USART  
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
11.09.2019, 14:31
DmitryDDDD, А сюда попадает?
C
1
2
3
4
5
void DMA2_Stream0_IRQHandler(void)
{
    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
    readyToTransmitFlag = 1;
}
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
11.09.2019, 14:34  [ТС]
_SayHello
Нет, крутится в while, до while тоже не попадает, но буфер при этом заполнился данными, т.е., если я правильно понимаю, прерывание DMA не срабатывает
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
11.09.2019, 14:42
DmitryDDDD, есть подозрения. У вас включаются прерывания АЦП, а обраьотчика не видно. Возможно это блокирует прерывания DMA. Уберите прерывания АЦП они вам не нужны.
C
1
2
3
    NVIC_EnableIRQ(ADC_IRQn);   
    
    ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
1
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
11.09.2019, 14:54  [ТС]
_SayHello , Вы правы, изменил, данные стали отправляться, корректные, спасибо. Есть еще правда пара вопросов: 1) После того, как верну настройку АЦП на 12 битную оцифровку, как-нибудь можно отправлять восемь 16 битных данных по USART, чтобы потом не пришлось их собирать из шестнадцати 8 битных чисел в терминале? 2) Частота работы ядра показывается 16 МГц, мне хотелось бы выполнить настройку на 100 МГц, я недавно создавал тему с вопросом как это можно реализовать, там необходимо менять файл, но у меня он подключен другой: system_stm32f4xx.c, можете подсказать по этому вопросу? Я могу написать Вам из той темы, чтобы не смешивать ее с этой
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
11.09.2019, 15:19
DmitryDDDD,
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
1) После того, как верну настройку АЦП на 12 битную оцифровку, как-нибудь можно отправлять восемь 16 битных данных по USART, чтобы потом не пришлось их собирать из шестнадцати 8 битных чисел в терминале?
К сожалению нет. USART отправляет порцию 8 бит. Собирать данные придется.
Если надо, чтобы в терминале просто отображались в виде строк, а не кодов, то надо делать преобразование в строку и ее уже отправлять.
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
Частота работы ядра показывается 16 МГц, мне хотелось бы выполнить настройку на 100 МГц, я недавно создавал тему с вопросом как это можно реализовать, там необходимо менять файл, но у меня он подключен другой: system_stm32f4xx.c, можете подсказать по этому вопросу?
Пишите в той. Одна тема - один вопрос.
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
11.09.2019, 15:22  [ТС]
_SayHello понял, спасибо. Сейчас из той темы напишу
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
11.09.2019, 15:22
Помогаю со студенческими работами здесь

Инициализация USART и передача данных: прокомментировать код
Помогите с комментариями к коду, не очень понял его. Кому не трудно к каждой сроке комментарий напишите?! Программа на языке ассемблера...

STM32 USART-RS485 передача пакета данных
Приветствую всех! Подскажите пожалуйста по следующему вопросу: Передаю байт ПК -&gt; STM32, по схеме ПК-&gt;USB/RS485 - драйвер...

Передача данных по SPI, между АЦП и микроконтроллером
Добрый день. Понемногу разбираясь с микроконтроллерами, решил связать МК с АЦП посредством SPI. Но, как мне кажется, возникла проблема: ...

Stm32f4 usart + внешний ацп
Добрый день, столкнулся с необычным мне ситуацией, камень stm32f407vet6 делаю обмен данными с ПК через usart. На порт С подключен внешний...

Работа с АЦП PIC18F4550 и передача данных на верхний уровень
Здравствуйте. Имею следующую задачу. На мк сформировать массив данных с АЦП, отфильтровать его и отправить на мк. Но мне немножко непонятен...


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

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru