Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
DmitryDDDD
0 / 0 / 0
Регистрация: 12.11.2018
Сообщений: 66
1

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

09.09.2019, 14:45. Просмотров 960. Ответов 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)
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.09.2019, 14:45
Ответы с готовыми решениями:

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

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

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

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

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

16
locm
2228 / 985 / 125
Регистрация: 28.10.2011
Сообщений: 3,320
Записей в блоге: 6
09.09.2019, 15:24 2
Цитата Сообщение от 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
731 / 434 / 140
Регистрация: 30.07.2015
Сообщений: 1,472
09.09.2019, 15:29 3
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
locm
2228 / 985 / 125
Регистрация: 28.10.2011
Сообщений: 3,320
Записей в блоге: 6
09.09.2019, 15:44 4
Цитата Сообщение от _SayHello Посмотреть сообщение
у вас отправится только младший байт измерений
На самом деле отправляется данные 2.5 каналов. DMA буфер __IO uint16_t ADC1ConvertedValue[5]; В функции передачи указатель на массив преобразуется в char* (в МК должен быть эквивалентен uint8_t*) и отправляется через USART. Но т. к. массив имеет размер 10 байт, а отправляется только 5, получается 2.5 канала, как бы странно это не звучало.

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

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

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
731 / 434 / 140
Регистрация: 30.07.2015
Сообщений: 1,472
11.09.2019, 14:11 7
Лучший ответ Сообщение было отмечено 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
DmitryDDDD
0 / 0 / 0
Регистрация: 12.11.2018
Сообщений: 66
11.09.2019, 14:18  [ТС] 8
_SayHello, изменил код, буфер так же заполняется, данные перестали отправляться

readyToTransmitFlag объявил как uint8_t, в цикле while так же пробовал изменять условие на if (readyToTransmitFlag == 1)
0
_SayHello
731 / 434 / 140
Регистрация: 30.07.2015
Сообщений: 1,472
11.09.2019, 14:23 9
DmitryDDDD, Настройку USART скиньте текущую. Что отладчик говорит?
0
DmitryDDDD
0 / 0 / 0
Регистрация: 12.11.2018
Сообщений: 66
11.09.2019, 14:25  [ТС] 10
_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
DmitryDDDD
0 / 0 / 0
Регистрация: 12.11.2018
Сообщений: 66
11.09.2019, 14:29  [ТС] 11
В цикле while отладчик не попадаетт в условие if, только проверяет его бесконечно
0
Миниатюры
Передача данных от АЦП по USART  
_SayHello
731 / 434 / 140
Регистрация: 30.07.2015
Сообщений: 1,472
11.09.2019, 14:31 12
DmitryDDDD, А сюда попадает?
C
1
2
3
4
5
void DMA2_Stream0_IRQHandler(void)
{
    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
    readyToTransmitFlag = 1;
}
0
DmitryDDDD
0 / 0 / 0
Регистрация: 12.11.2018
Сообщений: 66
11.09.2019, 14:34  [ТС] 13
_SayHello
Нет, крутится в while, до while тоже не попадает, но буфер при этом заполнился данными, т.е., если я правильно понимаю, прерывание DMA не срабатывает
0
_SayHello
731 / 434 / 140
Регистрация: 30.07.2015
Сообщений: 1,472
11.09.2019, 14:42 14
DmitryDDDD, есть подозрения. У вас включаются прерывания АЦП, а обраьотчика не видно. Возможно это блокирует прерывания DMA. Уберите прерывания АЦП они вам не нужны.
C
1
2
3
    NVIC_EnableIRQ(ADC_IRQn);   
    
    ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
1
DmitryDDDD
0 / 0 / 0
Регистрация: 12.11.2018
Сообщений: 66
11.09.2019, 14:54  [ТС] 15
_SayHello , Вы правы, изменил, данные стали отправляться, корректные, спасибо. Есть еще правда пара вопросов: 1) После того, как верну настройку АЦП на 12 битную оцифровку, как-нибудь можно отправлять восемь 16 битных данных по USART, чтобы потом не пришлось их собирать из шестнадцати 8 битных чисел в терминале? 2) Частота работы ядра показывается 16 МГц, мне хотелось бы выполнить настройку на 100 МГц, я недавно создавал тему с вопросом как это можно реализовать, там необходимо менять файл, но у меня он подключен другой: system_stm32f4xx.c, можете подсказать по этому вопросу? Я могу написать Вам из той темы, чтобы не смешивать ее с этой
0
_SayHello
731 / 434 / 140
Регистрация: 30.07.2015
Сообщений: 1,472
11.09.2019, 15:19 16
DmitryDDDD,
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
1) После того, как верну настройку АЦП на 12 битную оцифровку, как-нибудь можно отправлять восемь 16 битных данных по USART, чтобы потом не пришлось их собирать из шестнадцати 8 битных чисел в терминале?
К сожалению нет. USART отправляет порцию 8 бит. Собирать данные придется.
Если надо, чтобы в терминале просто отображались в виде строк, а не кодов, то надо делать преобразование в строку и ее уже отправлять.
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
Частота работы ядра показывается 16 МГц, мне хотелось бы выполнить настройку на 100 МГц, я недавно создавал тему с вопросом как это можно реализовать, там необходимо менять файл, но у меня он подключен другой: system_stm32f4xx.c, можете подсказать по этому вопросу?
Пишите в той. Одна тема - один вопрос.
0
DmitryDDDD
0 / 0 / 0
Регистрация: 12.11.2018
Сообщений: 66
11.09.2019, 15:22  [ТС] 17
_SayHello понял, спасибо. Сейчас из той темы напишу
0
11.09.2019, 15:22
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.09.2019, 15:22

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

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

Передача 1 бита по Usart
Добрый день, форуму. всем по чашке крепкого кофе. кто подскажет? из оборудования - Stm32F407 +...


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

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru