stm32, 2 вопрос по USART + ваш совет

Кто любит RISC в жизни, заходим, не стесняемся.
godz320
Родился
Сообщения: 19
Зарегистрирован: Пт янв 08, 2016 19:00:40

Re: stm32, 2 вопрос по USART + ваш совет

Сообщение godz320 »

ну вот, вроде получилось сделать передачу в USART через DMA с минимальными затратами процессора. Процу нечего не надо ждать!

кому не лень, посмотрите пож-ста.
Спойлер

Код: Выделить всё

#include "stm32f10x.h"   
#include "stdio.h"
#include "string.h"
#include "stdbool.h"

void initUsart(void);
bool sendToUsart(char* text);


// Буфер на отправку
#define SENDBUFFERSIZE	100
// Скорость передачи USART
#define BAUDRATE 9600



// Глобальные переменные 
char buffToSend [SENDBUFFERSIZE]; // буфер данных для передачи
int addrStart = 0;  // начальный адрес в буфере для передачи данных, на сессию DMA
int cntToSend = 0;  // кол-во байт для передачи
bool isNewData = false; // есть ли новые данные для открытие сессии передачи по DMA?!




// Обработчик прерываения по DMA, 4 канал
void DMA1_Channel4_IRQHandler(void)

{
			//если передача DMA завершена 
		if( DMA1->ISR & DMA_ISR_TCIF4)
		{
			// сбрасываем бит, transfer complete
			DMA1->IFCR |= DMA_IFCR_CTCIF4;
			// выключаем DMA канал
			DMA1_Channel4->CCR &= ~ DMA_CCR4_EN;


					// есть ли еще что отправлять?
					if(isNewData)
					{
						// сбрасываем флаг
						isNewData = false;
						
						
						DMA1_Channel4->CMAR = (uint32_t)&buffToSend[0] + addrStart ; // Начайльный адрес в памяти откруда брать + смещение
						DMA1_Channel4->CNDTR = cntToSend; // сколько передавать
						DMA1_Channel4->CCR |= DMA_CCR4_EN; // начинаем сессию передачи

					}	
					
					else
					{
							// очищаем кол-во данных для отправки, адрес на начало. Типа отправили все что было в буфере
								cntToSend = 0;
								addrStart = 0; 
							
					}


		}


}


void initUsart(void)
{
	//	Включаем питание на порт А
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN ;		
	//	Включаем питание на USART1
	RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
	//	Включаем питание на альтернативные функции 
	RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
	//	Включаем питание DMA1
	RCC->AHBENR |= RCC_AHBENR_DMA1EN;

	
	// Пин 9: 2 Мгц, альтернативный , Push-Pull
	GPIOA->CRH |= GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9_1;
	// Пин 10: 2 Мгц, альтернативный , Push-Pull
	GPIOA->CRH |= GPIO_CRH_CNF10_1 | GPIO_CRH_MODE10_1;  
	
	// Устанавливаем скорость обмена
	USART1->BRR =  (SystemCoreClock / BAUDRATE);  //0x1D4C;
	// Включаем USART1 , разрешаем отправку данных
	USART1->CR1 |= USART_CR1_UE | USART_CR1_TE ; // |USART_CR1_TXEIE;
	// Разрешаем использовать DMA на передачу 
	USART1->CR3 |= USART_CR3_DMAT ;


	// Настройка DMA
	//------------------------------------

	DMA1_Channel4->CCR = 0; // очищаем конфигурационный регистр
	DMA1_Channel4->CCR |= DMA_CCR4_MINC; //  Memory increment mode
	DMA1_Channel4->CCR |= DMA_CCR4_TCIE; // Transfer complete interrupt enable
	DMA1_Channel4->CCR |= DMA_CCR4_DIR; // режим данные из памяти 
	DMA1_Channel4->CPAR = (uint32_t)&(USART1->DR); //  Адрес дата регистра USART1, куда посылать
	
	

	// Устанавливаем прерывание по DMA канал 4
	NVIC_EnableIRQ(DMA1_Channel4_IRQn);
	
}


// функция передачи в USART через DMA
bool sendToUsartDma(char* text)
{

	// для цикла добавления данных в массив
	int i;	
	// получаем размер входной сроки
	int lenghtText = strlen(text);

	
	// если размер входной строки больше буфера, выходим с ощибкой
	if( lenghtText > SENDBUFFERSIZE ) return false;
	// если буфер переполнен, выходим с ошибкой
	if( (addrStart + cntToSend + lenghtText) >  SENDBUFFERSIZE) return false;
	
	// заполняем буфер или добавляем в буфер новые данные
	for(i = 0;i < lenghtText; i++)
	buffToSend[i + addrStart + cntToSend ] = text[i]; //
	
	//  если канал DMA свободен
	 if( (DMA1_Channel4->CCR & DMA_CCR4_EN) == 0)
	{		
			addrStart += lenghtText; // увеличиваем начальный адрес, для следующей передачи

			DMA1_Channel4->CMAR = (uint32_t)&buffToSend[0]; // Начайльный адрес в памяти откруда брать
			DMA1_Channel4->CNDTR = lenghtText; // длина передачи
			DMA1_Channel4->CCR |= DMA_CCR4_EN; // передаем

				
			
	}
		// иначе же, 
	else
		{
			isNewData = true; // устанавливаем флаг, что есть еще данные для передачи 
			cntToSend += lenghtText; // и увеличиваем кол-во байт для передачи
		}	
	


	
	// выходим без ошибки
	return true;

}


int main(void)
{
	
	// Инициализация USART1
	initUsart();
		
	// посылаем первую передачу
	sendToUsartDma("Hello, ");
	// сразу же еще
	sendToUsartDma("my name is ");
	// еще 
	sendToUsartDma("Aleksei...");
	// еще
	sendToUsartDma("\r\n");
	

	
	while(1)
	{
		
	}
	
	
	
}



Реклама
Ответить

Вернуться в «ARM»