кому не лень, посмотрите пож-ста.
Спойлер
Код: Выделить всё
#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)
{
}
}