Está en la página 1de 31

GERSON A.

PEREZ DMA EN STM32


VILLARROEL
(DIRECT MEMORY ACCESS)
DMA (ACCESO DIRECTO A MEMORIA)
DMA (ACCESO DIRECTO A MEMORIA)
DMA (ACCESO DIRECTO A MEMORIA)

El controlador de Acceso Directo a Memoria (Direct Memory Access - DMA) es una


unidad de hardware dedicada y programable que permite a los periféricos del
microcontrolador acceder a las memorias internas, sin la intervención del procesador.

El DMA está diseñado para trabajar en ambos sentidos, permite la transferencia de datos
desde la memoria a un periférico y desde un periférico a la memoria.

Todos los microcontroladores STM32 proveen por lo menos un controlador DMA, pero
la mayoría implementa dos controladores DMA independientes.

EL STM32F103 tiene 2 controladores DMA y 12 canales en total (7 para el DMA1 y 5


para el DMA2), cada uno dedicado a administrar los requerimientos de acceso a
memoria de uno o más periféricos.
DMA (ACCESO DIRECTO A MEMORIA)

Requerimientos de cada canal para el DMA1


DMA (ACCESO DIRECTO A MEMORIA)
DMA (ACCESO DIRECTO A MEMORIA)

Requerimientos de cada canal para el DMA2


DMA (ACCESO DIRECTO A MEMORIA)
DMA (ACCESO DIRECTO A MEMORIA)

Las configuraciones de DMA/Canal se realizan


usando una instancia de la estructura
DMA_InitTypeDef.

typedef struct {
uint32_t Direction;
uint32_t PeriphInc;
uint32_t MemInc;
uint32_t PeriphDataAlignment;
uint32_t MemDataAlignment;
uint32_t Mode;
uint32_t Priority;
} DMA_InitTypeDef;
DMA (ACCESO DIRECTO A MEMORIA) UART EN MODO DMA

• Ejemplo: Programa que envía y recibe datos por UART usando


DMA con interrupción.
...
uint8_t rx_completo = 0;
uint8_t tx_completo = 0;
...
int main(void)
{
uint8_t mensaje1[]="\r\nIntroducir tres caracteres: \r\n";
uint8_t mensaje2[]="\r\nOK\r\n";
uint8_t datos_rx[8];
...
DMA (ACCESO DIRECTO A MEMORIA) UART EN MODO DMA

...
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
tx_completo = 0;
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)mensaje2, sizeof(mensaje2));
while(!tx_completo);
...
while (1)
{
tx_completo = 0;
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)mensaje1, sizeof(mensaje1));
while(!tx_completo);
rx_completo = 0;
HAL_UART_Receive_DMA(&huart1, (uint8_t *)datos_rx, 3);
while(!rx_completo);
...
DMA (ACCESO DIRECTO A MEMORIA) UART EN MODO DMA

...
tx_completo = 0;
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)datos_rx, 3);
while(!tx_completo);
}
tx_completo = 0;
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)mensaje2, sizeof(mensaje2));
while(!tx_completo);
DMA (ACCESO DIRECTO A MEMORIA) UART EN MODO DMA

...
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel4_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
/* DMA1_Channel5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
}
...
DMA (ACCESO DIRECTO A MEMORIA) UART EN MODO DMA
//Programa stm32f1xx_it.c
...
extern uint8_t rx_completo;
extern uint8_t tx_completo;
...
void DMA1_Channel4_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_usart1_tx);
}
void DMA1_Channel5_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_usart1_rx);
}
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1);
}
DMA (ACCESO DIRECTO A MEMORIA) UART EN MODO DMA

...
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
rx_completo = 1;
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
tx_completo = 1;
}
DMA (ACCESO DIRECTO A MEMORIA) UART EN MODO DMA
DMA (ACCESO DIRECTO A MEMORIA) UART EN MODO DMA
DMA (ACCESO DIRECTO A MEMORIA) UART EN MODO DMA
DMA (ACCESO DIRECTO A MEMORIA) ADC EN MODO DMA

Ejemplo: Programa que lee 3 canales de ADC en


modo SCAN con DMA.
...
uint8_t conv_completa = 0
...
int main(void)
{
/* USER CODE BEGIN 1 */
char mensaje[20];
char mensaje2[] = "\r\nOK\r\n";
uint16_t lecturas_adc[3];
...
DMA (ACCESO DIRECTO A MEMORIA) ADC EN MODO DMA

• Ejemplo: Programa que lee 3 canales de ADC en


modo SCAN con DMA.
DMA (ACCESO DIRECTO A MEMORIA) ADC EN MODO DMA
DMA (ACCESO DIRECTO A MEMORIA) ADC EN MODO DMA
DMA (ACCESO DIRECTO A MEMORIA) ADC EN MODO DMA
DMA (ACCESO DIRECTO A MEMORIA) ADC EN MODO DMA
DMA (ACCESO DIRECTO A MEMORIA) ADC EN MODO DMA
DMA (ACCESO DIRECTO A MEMORIA) ADC EN MODO DMA

...
uint8_t conv_completa = 0
...
int main(void)
{
/* USER CODE BEGIN 1 */
char mensaje[20];
char mensaje2[] = "\r\nOK\r\n";
uint16_t lecturas_adc[3];
...
DMA (ACCESO DIRECTO A MEMORIA) ADC EN MODO DMA

...
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_ADCEx_Calibration_Start(&hadc1);
...
while (1)
{
HAL_UART_Transmit(&huart1, (uint8_t*) mensaje2, sizeof(mensaje2), HAL_MAX_DELAY);
conv_completa = 0;
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)lecturas_adc, 3);
while(!conv_completa);
//Ojo con tiempo de conversión del sensor de temperatura
...
DMA (ACCESO DIRECTO A MEMORIA) ADC EN MODO DMA

...
for(uint8_t i = 0; i < 3; i++)
{
sprintf(mensaje, "ADC %d: %hu\r\n", i, lecturas_adc[i]);
HAL_UART_Transmit(&huart1, (uint8_t*) mensaje, strlen(mensaje), HAL_MAX_DELAY);
}
HAL_Delay(500);
}
}
DMA (ACCESO DIRECTO A MEMORIA) ADC EN MODO DMA

...
static void MX_ADC1_Init(void)
{
...
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 3;
...
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
...
DMA (ACCESO DIRECTO A MEMORIA) ADC EN MODO DMA

...
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
...
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.Rank = ADC_REGULAR_RANK_3;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
...
}
static void MX_DMA_Init(void)
{
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
DMA (ACCESO DIRECTO A MEMORIA) ADC EN MODO DMA

//Programa stm32f1xx_it.c
...
extern uint8_t conv_completa;
...
void DMA1_Channel1_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_adc1);
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
conv_completa = 1;
}

También podría gustarte