Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту


 
Опции темы
Непрочитано 05.03.2014, 15:54  
hubble
Прописка
 
Регистрация: 04.08.2006
Сообщений: 139
Сказал спасибо: 12
Сказали Спасибо 12 раз(а) в 11 сообщении(ях)
hubble на пути к лучшему
По умолчанию STM32F4xx. Прерывания Half Transfer, Transfer Complete. Не понятные моменты

Объясните, пожалуйста, как правильно работать с прерываниями Half Transfer, Transfer Complete? Я понимаю, что по очереди, т.е., пришло прерывание Half Transfer, начинаю в нем подготавливать/обрабатывать полученные данные. А за это время приходит прерывание Transfer Complete. И та же процедура в нем. Затем все по кругу.
Есть rxBuffer на восемь байт. Принимается строка через USART - 10 байт, (например: "1234567890"). Так вот, когда приходит прерывание Half Transfer, то в нем пришедшие данные располагаются таким образом - 90345678. Т.е., заполнился весь буфер целиком плюс последние два байта перезаписались поверх первых двух затерлись.
Я предполагал, что в первом прерывании в буфер попадает 1234. С ними работаю. Во втором прерывании - 5678. Теперь с этими работаю. Далее снова в первом - 0912 и так далее.
Каким образом прочитать первые байты?

Код:
#include "stm32f4xx.h"
#include "misc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_usart.h"
#include "stm32f4xx_dma.h"
#include ‹stdio.h›

#define baudrate 9600
#define BUF_SIZE 8

unsigned char rxBuffer[BUF_SIZE];
/***********************************************/
void GPIO_Config(void);
void Usart_Config(void);
void DMA_Config(void);
void DMA1_Stream5_IRQHandler(void);
/**************************************************  **********************************************/
void GPIO_Config(void)
{
	GPIO_InitTypeDef porta;		
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	
	porta.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;		// PA2 --› usart2_TX, PA3 --› usart2_RX
	porta.GPIO_Mode = GPIO_Mode_AF;
	porta.GPIO_OType = GPIO_OType_PP;
	porta.GPIO_PuPd = GPIO_PuPd_NOPULL;
	porta.GPIO_Speed = GPIO_Speed_25MHz;
	GPIO_Init(GPIOA, &porta);
	
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);		// GPIOA
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);		// GPIOA
}
/**************************************************  **********************************************/
// Конфигурация usart2
void Usart_Config(void)
{
	USART_InitTypeDef usart2;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

	USART_DeInit(USART2);
	usart2.USART_BaudRate = baudrate;
	usart2.USART_WordLength = USART_WordLength_8b;
	usart2.USART_StopBits = USART_StopBits_1;
	usart2.USART_Parity = USART_Parity_No;
	usart2.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	usart2.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART2, &usart2);
	
	USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);		
	USART_Cmd(USART2, ENABLE);
}
/**************************************************  **********************************************/
void DMA_Config(void)
{
	DMA_InitTypeDef dma1;
	NVIC_InitTypeDef nvicdma1;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
	
	DMA_DeInit(DMA1_Stream5);
	dma1.DMA_Channel = DMA_Channel_4; 
	dma1.DMA_PeripheralBaseAddr = (uint32_t)&(USART2-›DR);
	dma1.DMA_Memory0BaseAddr = (uint32_t)rxBuffer; 
	dma1.DMA_DIR = DMA_DIR_PeripheralToMemory;
	dma1.DMA_BufferSize = BUF_SIZE;  	
	dma1.DMA_PeripheralInc = DMA_PeripheralInc_Disable;   
	dma1.DMA_MemoryInc = DMA_MemoryInc_Enable;        
	dma1.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	dma1.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	dma1.DMA_Mode = DMA_Mode_Circular;			// Циклический прием данных            
	dma1.DMA_Priority = DMA_Priority_Low;     
	dma1.DMA_FIFOMode = DMA_FIFOMode_Disable; 
	dma1.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull; 
	dma1.DMA_MemoryBurst = DMA_MemoryBurst_Single;   
	dma1.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 
	DMA_Init(DMA1_Stream5, &dma1);
	
	DMA_ITConfig(DMA1_Stream5, DMA_IT_HT | DMA_IT_TC, ENABLE);	

	nvicdma1.NVIC_IRQChannel = DMA1_Stream5_IRQn;	
	nvicdma1.NVIC_IRQChannelPreemptionPriority = 0;
	nvicdma1.NVIC_IRQChannelSubPriority = 0;
	nvicdma1.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&nvicdma1);
}
/**************************************************  **********************************************/
void DMA1_Stream5_IRQHandler(void)
{
	if(DMA_GetITStatus(DMA1_Stream5, DMA_IT_HTIF5) == SET) {
		DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_HTIF5);
		

	}
	/************************************************/
	if(DMA_GetITStatus(DMA1_Stream5, DMA_IT_TCIF5) == SET) {
		DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TCIF5);


	}
}
/**************************************************  **********************************************/
int main(void)
{
	GPIO_Config();
	Usart_Config();
	DMA_Config();

	DMA_Cmd(DMA1_Stream5, ENABLE);

	while(1) {

	}

	return 0;
}
Реклама:

Последний раз редактировалось hubble; 06.03.2014 в 12:24.
hubble вне форума  
Непрочитано 05.03.2014, 19:01  
Hives
Гражданин KAZUS.RU
 
Регистрация: 25.11.2010
Сообщений: 516
Сказал спасибо: 1
Сказали Спасибо 126 раз(а) в 109 сообщении(ях)
Hives на пути к лучшему
По умолчанию Re: STM32F4xx. Прерывания Half Transfer, Transfer Complete. Не понятные моменты

как предисловие - stm32 - это не тот камень где uart+dma - хорошая идея

где настройки частот? до main() или вообще пропущены?
скорость uart? чем смотрели пропуск/переполнение приемного буфера?
если отладчиком - то привет, приехали.

и да, HT/TC должно работать именно так как вы описали
Hives вне форума  
Непрочитано 06.03.2014, 12:24  
hubble
Прописка
 
Регистрация: 04.08.2006
Сообщений: 139
Сказал спасибо: 12
Сказали Спасибо 12 раз(а) в 11 сообщении(ях)
hubble на пути к лучшему
По умолчанию Re: STM32F4xx. Прерывания Half Transfer, Transfer Complete. Не понятные моменты

Спасибо, что ответили. Уже разобрался.
Действительно, в Кейле пользуюсь отладчиком. Плата STM32F4Discovery.
На каком-то форуме нашел, что смотреть работу в прерываниях на железе, используя отладчик, не выйдет (а я-то раньше в Протеусе это делал даже в прерываниях). Что придется поизвращаться. Именно это и не получалось. В общем, немного переделав код, получилось посмотреть переменные.
hubble вне форума  
Непрочитано 06.03.2014, 14:47  
hubble
Прописка
 
Регистрация: 04.08.2006
Сообщений: 139
Сказал спасибо: 12
Сказали Спасибо 12 раз(а) в 11 сообщении(ях)
hubble на пути к лучшему
По умолчанию Re: STM32F4xx. Прерывания Half Transfer, Transfer Complete. Не понятные моменты

Появились еще несколько вопросов.
Сообщение от Hives Посмотреть сообщение
как предисловие - stm32 - это не тот камень где uart+dma - хорошая идея
Пока еще не знаю, почему это так, но кое-какие сомнения появляются. Как бы там ни было, но допустим работать приходится именно в этой связке: usart + dma.
Каким образом получить полностью все данные?
Если, допустим, получаем 7 байт при 8-ми байтном буфере: 1234567. За первое прерывание будет получено 1234, за второе ... ничего, т.к. его просто не будет. Вернее, может быть данные и далее будут приниматься, но мне необходимо сейчас их получить и поработать с ними.
Подскажите, каким образом такое можно реализовать (не привлекая прерывание по приему каждого символа)? Или это не правильный подход?

Последний раз редактировалось hubble; 06.03.2014 в 14:51.
hubble вне форума  
Непрочитано 06.03.2014, 16:44  
Yurkin2014
Заблокирован
 
Регистрация: 21.01.2014
Сообщений: 589
Сказал спасибо: 7
Сказали Спасибо 267 раз(а) в 206 сообщении(ях)
Yurkin2014 на пути к лучшему
По умолчанию Re: STM32F4xx. Прерывания Half Transfer, Transfer Complete. Не понятные моменты

Вам нужно определиться: что значит все данные приняты и можно с ними работать?
1. Число байтов известно. Тогда кладём в ДМА это число и работаем как обсуждалось выше.
2. Число байтов неизвестно или может изменяться. Тогда признак конца, например, пауза в передаче, timeout. Тогда после приёма каждого байта в прерывании USART сбрасывать таймер. И как таймер переполнится - timeout, можно работать с данными.
3. Признак конца данных - спец.символ, например, 0xFF. Тогда анализировать каждый байт в прерывании USART на предмет окончания данных, а из данных исключить появление спец.символа, чтобы не было ложных срабатываний.
4 ...

Последний раз редактировалось Yurkin2014; 06.03.2014 в 16:47.
Yurkin2014 вне форума  
Непрочитано 06.03.2014, 19:24  
Boba_spb
Почётный гражданин KAZUS.RU
 
Регистрация: 08.06.2008
Сообщений: 1,394
Сказал спасибо: 4
Сказали Спасибо 183 раз(а) в 167 сообщении(ях)
Boba_spb на пути к лучшему
По умолчанию Re: STM32F4xx. Прерывания Half Transfer, Transfer Complete. Не понятные моменты

На скорости 9600 использовать DMA ???

В STM32F0 - аппаратное прерывание по заданному байту есть. Там DMA хорошо использовать на больших скоростях, но тоже не во всех протоколах.
Boba_spb вне форума  
Непрочитано 06.03.2014, 23:00  
Hives
Гражданин KAZUS.RU
 
Регистрация: 25.11.2010
Сообщений: 516
Сказал спасибо: 1
Сказали Спасибо 126 раз(а) в 109 сообщении(ях)
Hives на пути к лучшему
По умолчанию Re: STM32F4xx. Прерывания Half Transfer, Transfer Complete. Не понятные моменты

hubble а, собственно, чем не устраивает ловить каждый байт в прерывании?
обычное fifo берет ~30 тактов на прием байта - вполне шустро и +полный контроль над потоком
Hives вне форума  
Непрочитано 07.03.2014, 09:24  
Oleg Galizin
Частый гость
 
Регистрация: 25.03.2010
Адрес: Voronezh
Сообщений: 35
Сказал спасибо: 0
Сказали Спасибо 7 раз(а) в 7 сообщении(ях)
Oleg Galizin на пути к лучшему
По умолчанию Re: STM32F4xx. Прерывания Half Transfer, Transfer Complete. Не понятные моменты

Здравствуйте.
Здесь такое ощущение, что успевает заполнится весь буфер из 8 символов, но поскольку Вы передаете 10 символов, то последние 2 символа переписывают первые 2. Я думаю что здесь происходит следующее:
Вы попадаете в прерывание и останавливаетесь в отладчике, что бы посмотреть буфер. А dma в это время продолжает работать. Когда Вы смотрите содержимое - все уже принято и Вы имеете то что наблюдаете. Что бы посмотреть реальные данные, что были в буфере на момент HT прерывания, необходимо исключить задержку до просмотра. Скопируйте Ваш буфер в прерывании в другой буфер и уже после копирования поставьте точку останова. Тогда Вы увидите, что было в буфере в момент времени чуть чуть отстающий от выставления флага HT прерывания.

Последний раз редактировалось Oleg Galizin; 07.03.2014 в 09:27.
Oleg Galizin вне форума  
Непрочитано 07.03.2014, 11:21  
hubble
Прописка
 
Регистрация: 04.08.2006
Сообщений: 139
Сказал спасибо: 12
Сказали Спасибо 12 раз(а) в 11 сообщении(ях)
hubble на пути к лучшему
По умолчанию Re: STM32F4xx. Прерывания Half Transfer, Transfer Complete. Не понятные моменты

Сообщение от Boba_spb Посмотреть сообщение
На скорости 9600 использовать DMA ???
Я для примера взял эту скорость. Скорости будут другие. Да и передаваться будет совсем не 10 байт. Такое количество было взято для наглядности.
Сообщение от Hives Посмотреть сообщение
hubble а, собственно, чем не устраивает ловить каждый байт в прерывании?
Нет, нет. Меня такой вариант вполне устроит, если не смогу разобраться с приемом, используя DMA. Именно так всегда и делал. Но понять-то его работу (DMA) мне надо. И прерываний в проекте будет несколько. Да, собственно говоря, и существует зачем-то ведь такая связка - USART + DMA. Как я полагаю, такой вопрос (как забрать/передать последние байты) может возникнуть и при использовании ADC + DMA, DAC + DMA и т.д. Хотя с ними не работал. И, поэтому, не уверен в этом.
Сообщение от Oleg Galizin Посмотреть сообщение
Здравствуйте.
Здесь такое ощущение, что успевает заполнится весь буфер из 8 символов, но поскольку Вы передаете 10 символов, то последние 2 символа переписывают первые 2. Я думаю что здесь происходит следующее:
Вы попадаете в прерывание и останавливаетесь в отладчике, что бы посмотреть буфер. А dma в это время продолжает работать. Когда Вы смотрите содержимое - все уже принято и Вы имеете то что наблюдаете. Что бы посмотреть реальные данные, что были в буфере на момент HT прерывания, необходимо исключить задержку до просмотра. Скопируйте Ваш буфер в прерывании в другой буфер и уже после копирования поставьте точку останова. Тогда Вы увидите, что было в буфере в момент времени чуть чуть отстающий от выставления флага HT прерывания.
Да, именно так все и происходит. Спасибо за участие. Но с этим вопросом уже разобрался. Понял, как можно просматривать.

Остался лишь тот вопрос, который в сообщении №4.
Пришло сообщение. Большую его часть словил, а маленький кусочек в конце плюс контрольную сумму (например) нет. Вернее она в буфере лежит, но вот прерывания Half Transfer или Transfer Complete не наступили. Так как половина буфера или вторая половина еще не заполнились.

Последний раз редактировалось hubble; 07.03.2014 в 11:27.
hubble вне форума  
Непрочитано 07.03.2014, 17:58  
zgenius
Прохожий
 
Регистрация: 31.08.2010
Адрес: Красноярский край
Сообщений: 2
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
zgenius на пути к лучшему
По умолчанию Re: STM32F4xx. Прерывания Half Transfer, Transfer Complete. Не понятные моменты

Уважаемый, hubble.
В качестве решения вашей задачки предлагаю рассмотреть вариант использования двух буферов для приема данных по UART.
Для этого необходимо поток DMA настроить в режиме Double buffer mode – см. п.10.3.9 Reference manual RM0090 v.6. Настройка достаточно проста: в регистре DMA_SxCR необходимо установить бит DBM. В регистр DMA_SxM0AR занести адрес начала первого буфера. В регистр DMA_SxM1AR занести адрес начала второго буфера. Установить бит CT регистра DMA_SxCR в соответствии с тем, в какой буфер сначала будут записываться данные (лог. 0 – в буфер по адресу, указанному в DMA_SxM0AR, лог. 1 – по адресу DMA_SxM1AR). Прерывание DMA настроить по факту полного завершения передачи.
Процедура работы следующая:
1. Как только DMA выполнить заданное число пересылок (указанное в регистре DMA_SxNDTR) в буфер с номером CT, он переключит состояние бита CT и автоматически перейдет на запись данных в другой буфер. В это время возникнет прерывание по завершению пересылки данных (взведется бит TCIFx).
2. В прерывании Вы определяете путем чтения бита CT, с каким буфером сейчас работает DMA, и выполняете обработку полученных данных в другом буфере.
3. При необходимости, если обработка данных занимает времени больше, чем заполнение буфера, при входе в прерывание можно изменить адрес в регистре DMA_SxM0AR или DMA_SxM1AR (в зависимости от того, какой из регистров не используется), указав третий (четвертый, пятый и так далее) свободный буфер, на который в следующий раз переключится DMA.
У меня такой подход используется для работы с АЦП. Четыре буфера переключаются циклически для обеспечения сохранности данных во время занятости процессора.
zgenius вне форума  
 

Закладки
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход


Часовой пояс GMT +4, время: 18:51.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot