STM32F407VG, ADC+DMA+USART

Написал программу ADC+DMA+USART.Микроконтроллер STM32F407VG. Почему-то не работает. Не могу понять почему… Суть программы: При подаче напряжения на выход АЦП, DMA2 передает данные в память после чего DMA1 передает данные в USART3 который шлет все в PC

/*******************************************************************/
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_adc.h"
#include "stm32f4xx_exti.h"
#include "stm32f4xx_syscfg.h"
#include "stm32f4xx_usart.h"
#include "stm32f4xx_dma.h"
#include "misc.h"
/*******************************************************************/
uint16_t adc_buffer[64];
void ADC_INIT(void)
{
//ADC Initialization
ADC_InitTypeDef  ADC_InitStructure;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_Ext_IT11;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);

ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_3Cycles);
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);

//ADC On to work with DMA
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
}




void USART_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStructure;

// USART TX
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);
		GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
		GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
		GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
		GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

		GPIO_Init(GPIOB, &GPIO_InitStruct);	
	
//USART Initialization
		USART_InitStructure.USART_BaudRate = 115200;
		USART_InitStructure.USART_WordLength = USART_WordLength_8b;
		USART_InitStructure.USART_StopBits = USART_StopBits_1;
		USART_InitStructure.USART_Parity = USART_Parity_No ;
		USART_InitStructure.USART_HardwareFlowControl =USART_HardwareFlowControl_None;
		USART_InitStructure.USART_Mode = USART_Mode_Tx;
		USART_Init(USART3, &USART_InitStructure);
		USART_Cmd(USART3, ENABLE);
		USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE);
}

void DMA1_USART(void)
{
	DMA_InitTypeDef DMA_InitStructure;
  DMA_InitStructure.DMA_Channel = DMA_Channel_4;  
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(USART3->DR);
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&adc_buffer[0];
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStructure.DMA_BufferSize = 64;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
  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(DMA1_Stream1, &DMA_InitStructure);
  DMA_Cmd(DMA1_Stream1, ENABLE);
}

void DMA2_INIT(void)
{
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)&adc_buffer[0];	
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 64;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_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);   
}

void DMA2_Stream0_IRQHandler(void)
{ 
    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
  }
int main()
{
	NVIC_InitTypeDef NVIC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); 
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
	
//GPIO Initialization For ADC1
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOE, &GPIO_InitStruct);
	
//Interrapt from DMA
	NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	
    while(1)
    {
 	__NOP();
    }

}

  • -10
  • 12 ноября 2013, 02:12
  • Foxek

Комментарии (18)

RSS свернуть / развернуть
1) смотри предыдущий свой топик.
2) Разбивка длинной записи!!!
+3
При подаче напряжения на выход АЦП, DMA2 передает данные в память после чего DMA1 передает данные в USART3 который шлет все в PC
1) у АЦП входы, выход у ЦАП
2) тригер ADC_ExternalTrigConv_Ext_IT11 никогда мной не пробовался, но думаю он сработает только после конфигурации EXTI и то только на смену логических уровней на пине.
3)
//GPIO Initialization For ADC1
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOE, &GPIO_InitStruct);
GPIO_Mode_IN — это цифровой вход, а не аналоговый (для АЦП нужен аналоговый (как и ЦАП), а цифровой для того же EXTI)
4)
DMA_InitStructure.DMA_BufferSize = 64;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;

DMA_InitStructure.DMA_BufferSize = 64;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

при одном и том же размере буфера, разные типы данных, в итоге в usart, будет выбрасывать только половину uint16_t adc_buffer[64]
5)
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_Mode_IN -> опять же цифровой вход, нужен AF
GPIO_OType_PP -> OD
GPIO_PuPd_NOPULL -> PULL UP
6)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
нету DMA1, хотя он у тебя за USART3 отвечает
6) понял откуда ноги растут в настройках GPIO USART, DMA1_stream1 channel4 — это DMA для USART3_RX (смотрим ref manual стр.304) -> DMA1_stream3 channel4 (USART3_TX)
7)
//GPIO Initialization For ADC1
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOE, &GPIO_InitStruct);
PE11 вообще не является ADC (если я правильно понял автора, то по смене напряжения на нем он должен был отправлять данные по USART, и данные брать именно с него), но настроен он на
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_3Cycles);
а это PA6, настроек которого я вообще не вижу…
8)
void DMA2_Stream0_IRQHandler(void)
{
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
}
прерывание не делает ничего полезного, только разрешает себя повторять снова и снова, видимо чтобы немного разгрузить
while(1)
{
__NOP();
}
%)
для работы DMA не нужные прерывания, он и сам будет работать, настроенное прерывание нужно когда тебе необходимо что то сделать по окончании полной передачи настроенного буфера
9) из main не вызывается не одна из функций инициализации, тоесть у тебя ничего кроме
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
//GPIO Initialization For ADC1
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOE, &GPIO_InitStruct);
//Interrapt from DMA
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
не выполняется, после чего падает в вечный цикл, конечно работать не будет, просто наспросто не должно работать…
мне пора идти, на этом закончу поиск =) почитай два документа, они огромны, но на них все завязано
www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00037051.pdf
— шит, в котором можно найти все назначения всех ног портов ввода вывода (есть еще много чего другого)
www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf
— шит, в котором прописано почти все по настройке основных всех элементов микроконтроллера (за исключением битов лочки, и другого, чего пока тебе не нужно)
почитаешь-поймешь как все может и не может работать.
+1
Спасибо за найденные ошибки
-1
В добрый путь
0
Я делал ту задачу как тестовую чтобы проверить связку АЦП ДМА
0
И в той теме развели очень много бессмысленной болтовни совсем не на нужную мне тему
-3
Ого-го, светодиод уже по-видимому загорается в прерывании, или нет, Foxek???

Хоть-бы отписался что-ли, народ там холивар устроил по поводу твоих постов, а ты решил ещё керосинчеку подлить.
Ну-ну, писатель по-видимому становится читателем.
+1
И в той теме развели очень много бессмысленной болтовни совсем не на нужную мне тему
-3
А что вы ожидали, сами разводя темы, никому тут не интересные?
+2
То что это неинтересновам не значит что это не интересно никому. И вы как я посмотрю ничего умного и дельного пока не скпзали
-1
Вы таки думаете что ваши проблемы с кодом кому-то интересны? :)
+3
Я думаю решение проблем с этим кодом в итоге поможет начинающим таким же как я
-1
Посмотри примеры для работы с разными видами периферии и почитай документы, ARM cortex M4f довольно навороченная архитектура, понять что к чему мигом не получится, надо вникать как что работает, слишком много всего есть в камне STM32F407VG, чтоб новичку делать проект, использующий сразу 3 различных периферии(ADC,USART,DMA), причем в связке, и, судя по коду, ты пока не понимаешь как это все должно работать, у тебя все абстрактно, мой совет, сделай сначала следующее
1) Проект мигания светодиодом (камень такой же как в stm32f4-discovery, если юзаешь ее то проблем нет), причем в связке с кнопкой, пока не настроишь правильно RCC и GPIO — не заработает
2) Проект отправки/приема данных через USART — правильность в направлении на комп можно проверить имея шнурок USB-USART или COM-USART, в направлении на микроконтроллер проверяй принятое значение с известным и зажигай светодиод если принятое соответствует(в первом проекте научишься морганию). Причем есть один нюанс, можешь попасться на том, что не проверяя занятости порта на передачу, будешь постоянно класть в него данные, что приведет к мусору на входе компа, посмотри примеры реализации, их куча, напиши свой, сам напиши, и потестируй чтоб понять что зачем и почему
3) Проект получения данных от ADC и отправкой их в USART, без DMA, вручную
4) Проект отправки какого то буфера по USART через DMA, не ADC, а именно какой то буфер или строку символов, чтоб знать что конкретно ты должен получить и в каком порядке
5) Проект, который ты пытался реализовать в статье
Не пытайся построить верхушку пирамиды, не имея фундамента, даже если ты это сможешь, то при новом проекте легче тебе не будет, пока ты не будешь знать основы периферии и будешь с нуля строить новую верхушку, основы надо изучать по отдельности, потому как в связке они становятся сложнее, и работают по другому, логика работы устройств через DMA отличается от логики работы вручную и по прерываниям. Начни с простого, читай как это должно работать, примеров на stm32 уже столько, что можно солить…
+2
Спасибо за советы. А не могли бы вы написать и пояснить как настроить Ацп чтобы он включал преобразование когда на определенный пин приходил сигнал?
0
Нету такого понятия — приходит сигнал, если не оговорено что подразумевается под сигналом, на входе АЦП всегда что то есть, независимо от того подаете вы ножку что либо или нет, это как в старом одесском анекдоте:
— подскажите, если я пойду в ту сторону, там будет вокзал?
— я вас уверяю, он там будет даже если вы туда не пойдете…
АЦП обычно настраивают на срабатывание по таймеру, либо на постоянную заботу в цикле, так часто как только он может, есть конечно у АЦП analog watchdog, но он просто генерит прерывание при выходе значений АЦП за рамки установленных пределов.
Если хочешь определить изменение значения АЦП, то мне сразу пока не приходит на ум как это сделать аппаратными средствами, хотя думаю можно извратиться с помощью таймеров и дма, лучше делать это программно.
А теперь главное, не читай между строк, я уже дал совет что и как тебе следует сделать чтобы научиться чему то, а ты опять заладил свое, как построить верхушку пирамиды блин, да круглую и чтоб с дамами и преферансом… к тебе тут много негатива льют не просто так, тебя отправляют на форум, потому как это место для решения проблем и советов, у блогов другое назначение, вот когда ты сделаешь рабочий проект, использующий такие связки, которые еще никем небыли описаны, или были но есть существенное отличие, то добро пожаловать сюда, выкладывай проект, готовый проект, поясняй что и как там работает, вот чего ждут в блоге, лично я тут жду этого, а не вопросов, отвечаю я на эти вопросы, чтобы ты тему эту больше не плодил, не комильфо это…
+2
«Да ямбись оно хореем через амфибрахий!»
Уж сообщество не торт — сборник эпитафий…
0
Кто нибудь поможет тут начинающему?
-1
Как уже советовали Вам, лучше обратитесь на форум! Он для этого больше подходит… А результат рабочий потом уж и здесь выложить не грех, со всеми плюшками и наворотами
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.