历史上的今天
返回首页

历史上的今天

今天是:2024年10月19日(星期六)

正在发生

2021年10月19日 | stm32专题十三:DMA(三)存储器到外设

2021-10-19 来源:eefocus

DMA的存储器到外设的配置,其实和存储器到存储器的配置非常类似。


只是需要注意一点,就是外设寄存器的地址如何获得?比如USART->DR数据寄存器,我们可以这样定义(基址 + 偏移)


// 外设寄存器地址

#define USART_DR_ADDRESS        (USART1_BASE + 0x04)

然后的配置就跟USART和DMA非常类似,直接上初始化过程:


bsp_dma.c


#include "bsp_dma.h"

#include

 

uint8_t SendBuff[SENDBUFF_SIZE];

 

void USART_Config(void)

{

  GPIO_InitTypeDef GPIO_InitStruct;

USART_InitTypeDef USART_InitStruct;

// 开启串口的GPIO时钟

DEBUG_UASRT_GPIO_APBxClkCmd(DEBUG_UASRT_GPIO_CLK, ENABLE);

 

  // USART的TX配置为复用推挽输出

GPIO_InitStruct.GPIO_Pin = DEBUG_UASRT_TX_GPIO_PIN;

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(DEBUG_UASRT_TX_GPIO_PORT, &GPIO_InitStruct);

// USART的RX配置为浮空输入(由中文参考手册查询)

GPIO_InitStruct.GPIO_Pin = DEBUG_UASRT_RX_GPIO_PIN;

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(DEBUG_UASRT_RX_GPIO_PORT, &GPIO_InitStruct);

// 开启串口时钟

DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);

// 配置串口参数(波特率、8位数据、1位停止位、无校验、发送接收模式、无硬件流控)

USART_InitStruct.USART_BaudRate = DEBUG_USART_BAUDRATE;

USART_InitStruct.USART_WordLength = USART_WordLength_8b;

USART_InitStruct.USART_StopBits = USART_StopBits_1;

USART_InitStruct.USART_Parity = USART_Parity_No;

USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

USART_Init(DEBUG_USARTx, &USART_InitStruct);

 

// 使能串口

USART_Cmd(DEBUG_USARTx, ENABLE);

}

 

int fputc(int ch, FILE *f)

{

USART_SendData(DEBUG_USARTx, (uint8_t)ch);

while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);

 

return ch;

}

 

// Memory -> P(USART->DR)

void USARTx_DMA_Config(void)

{

DMA_InitTypeDef DMA_InitStruct;

// 开时钟,我经常会忘记这一步(DMA挂载在AHB总线)

RCC_AHBPeriphClockCmd(USART_TX_DMA_CLK, ENABLE);

// 配置初始化结构体

DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)USART_DR_ADDRESS;

DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)SendBuff;

/* DMA_DIR_PeripheralSRC:外设为源,DMA_DIR_PeripheralDST:外设为目的地 */

DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;

DMA_InitStruct.DMA_BufferSize = SENDBUFF_SIZE;

DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;

DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;

DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel4, &DMA_InitStruct);

DMA_Cmd(DMA1_Channel4, ENABLE);

}

bsp_dma.h头文件


#ifndef __BSP_DMA_H

#define __BSP_DMA_H

 

#include "stm32f10x.h"

 

// 串口1 USART1

#define DEBUG_USARTx    USART1

#define DEBUG_USART_BAUDRATE    115200

#define DEBUG_USART_CLK    RCC_APB2Periph_USART1

#define DEBUG_USART_APBxClkCmd    RCC_APB2PeriphClockCmd

 

// USART GPIO引脚宏定义

#define DEBUG_UASRT_GPIO_CLK RCC_APB2Periph_GPIOA

#define DEBUG_UASRT_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd

 

#define DEBUG_UASRT_TX_GPIO_PORT GPIOA

#define DEBUG_UASRT_TX_GPIO_PIN GPIO_Pin_9

#define DEBUG_UASRT_RX_GPIO_PORT GPIOA

#define DEBUG_UASRT_RX_GPIO_PIN GPIO_Pin_10

 

 

#define USART_TX_DMA_CLK RCC_AHBPeriph_DMA1

// 外设寄存器地址

#define USART_DR_ADDRESS        (USART1_BASE + 0x04)

// 一次发送的数据量

#define SENDBUFF_SIZE            5000

// 串口对应的DMA请求通道

#define USART_TX_DMA_CHANNEL      DMA1_Channel4

 

extern uint8_t SendBuff[SENDBUFF_SIZE];

 

void USART_Config(void);

void USARTx_DMA_Config(void);

 

 

#endif /* __BSP_DMA_H */

然后再主函数中进行调用。注意,这里有一点与Memory to Memory不同,MtM一旦使能就会进行传输,不需要触发。而这里需要USART发送一个DMA请求,然后DMA才会开始进行数据传输,请求函数为:


/**

  * @brief  Enables or disables the USART抯 DMA interface.

  * @param  USARTx: Select the USART or the UART peripheral. 

  *   This parameter can be one of the following values:

  *   USART1, USART2, USART3, UART4 or UART5.

  * @param  USART_DMAReq: specifies the DMA request.

  *   This parameter can be any combination of the following values:

  *     @arg USART_DMAReq_Tx: USART DMA transmit request

  *     @arg USART_DMAReq_Rx: USART DMA receive request

  * @param  NewState: new state of the DMA Request sources.

  *   This parameter can be: ENABLE or DISABLE. 

  * @retval None

  */

void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState)

{

  if (NewState != DISABLE)

  {

    /* Enable the DMA transfer for selected requests by setting the DMAT and/or

       DMAR bits in the USART CR3 register */

    USARTx->CR3 |= USART_DMAReq;

  }

  else

  {

    /* Disable the DMA transfer for selected requests by clearing the DMAT and/or

       DMAR bits in the USART CR3 register */

    USARTx->CR3 &= (uint16_t)~USART_DMAReq;

  }

}

可以看到,USART-DMA请求函数,实际上配置的是UASRT_CR3寄存器,两个参数如下,分别配置的是CR3的第7位和第6位,对应发送请求使能和接受请求使能。


#define USART_DMAReq_Tx                      ((uint16_t)0x0080)

#define USART_DMAReq_Rx                      ((uint16_t)0x0040)

我们在完成初始化配置后,调用这个USART_DMACmd函数,DMA就会立刻开始传输。


在主函数中进行测试


main.c


#include "stm32f10x.h"

#include "bsp_led.h"

#include "bsp_dma.h"

 

void delay(uint32_t count);

 

int main(void)

{

uint16_t i = 0;

LED_GPIO_Config();

USART_Config();

USARTx_DMA_Config();

for (; i < SENDBUFF_SIZE; i++)

{

SendBuff[i] = 'P';

}

USART_DMACmd(DEBUG_USARTx, USART_DMAReq_Tx, ENABLE);

 

while (1)

{

LED_R_TOGGLE;

delay(0XFFFFF);

}

}

 

void delay(uint32_t count)

{

for (; count != 0; count--);

}

推荐阅读

史海拾趣

EBK Kruger GmbH & Co KG公司的发展小趣事

面对数字化浪潮的挑战,EBK Kruger积极拥抱数字化转型。公司引入了先进的ERP系统和智能制造技术,提高了生产效率和产品质量。同时,EBK Kruger还加强了对大数据和人工智能技术的研发和应用,为客户提供了更加智能化和个性化的产品和服务。通过数字化转型的推动,EBK Kruger在激烈的市场竞争中保持了领先地位。

DELTA公司的发展小趣事

Delta公司始终将技术创新作为推动企业发展的核心动力。公司不断投入巨资进行技术研发和创新,积极引进先进技术和设备,培养高素质的研发人才。这些努力使Delta在电源管理、能源管理、智能绿生活等领域取得了多项技术突破和专利成果,不仅提升了公司的核心竞争力,还引领了整个行业的发展方向。

大毅科技公司的发展小趣事

为了进一步提升产品质量和竞争力,大毅科技积极申请并获得了多项国际品质认证,如ISO9001、ISO14001、TS16949等。这些认证不仅证明了大毅科技在品质管理方面的卓越能力,还为公司打开了通往国际市场的大门。随着认证的不断增多,大毅科技的产品开始出口到全球各地,与索尼、雅马哈等知名企业建立了长期合作关系。

Caddock公司的发展小趣事

多年来,Caddock公司一直致力于电阻材料技术的研究与创新。通过不断的努力,公司的电阻器技术逐渐扩展到更低的温度系数、更高的稳定性、更好的瞬态处理以及更高和更低的电阻率。这些技术进步使得Caddock公司的电阻器和电阻器网络系列不断丰富,满足了市场的多样化需求。

芯朋微电子(chipown)公司的发展小趣事

作为国内电源管理芯片的重要厂商,芯朋微电子一直致力于实现进口替代。公司不断投入研发,推出了一系列高效能、低功耗、品质稳定的电源管理集成电路产品,推动整机的能效提升和技术升级。这些努力使得芯朋微电子在国内电源管理芯片市场中的地位日益稳固。

Baumer Electric Ag公司的发展小趣事

1962年,赫尔穆特•维茨(Helmut Vietze)加入Baumer Electric Ag,成为一名模具制造工。他凭借出色的个人能力和工作表现,很快在公司中脱颖而出。1964年,公司创始人Herbert Baumer去世后,Helmut Vietze接管了管理层,并带领公司走向新的发展阶段。他的领导为公司注入了新的活力,推动了Baumer在技术和市场上的双重突破。

问答坊 | AI 解惑

基于ARM的条码精密测量系统

摘要: 本文介绍了一种基于32位高性能处理器的视觉精密测量系统的软硬件设计。图像传感器采集的条码图像通过精密定位算法得到绝对位移值,由以太网接口实现高速图像采集。该系统适用于高精度定位的各种位移测量。 关键词: ARM;嵌入式系统;视觉 ...…

查看全部问答>

LTCC的前景

本人初涉LTCC产品设计,不知基于该工艺的产品前景如何,谢谢讨论。…

查看全部问答>

模拟电子200问

附:pdf文档 1、半导体材料制作电子器件与传统的真空电子器件相比有什么特点? 答:频率特性好、体积小、功耗小,便于电路的集成化产品的袖珍化,此外在坚固抗震可靠等方面也特别突出;但是在失真度和稳定性等方面不及真空器件。 2、什么 ...…

查看全部问答>

NXL LPC系列ARM IIC总线下读写AT24Cxx的总结

       最近应用到NXP LPC系列的ARM IIC总线进行读写AT24Cxx EEPROM,总是出现一下错误,经过查阅资料才发现,原来本人范的全是最基本的错误,感觉很惭愧,现在把容易出错的地方进行总结,希望网友遇到这样的问题时 ...…

查看全部问答>

S3C6410 WINCE6 SD卡升级 求解

最近在思考一个问题,就是有关SD卡升级的。 我看到过三星发布2442下的SD卡升级,但有个缺陷是只支持FAT格式的小容量卡,而且,在EBOOT里面去读写卡的block、sector,简直有点复杂。 我在想,如果是FAT32格式的(现在基本上都是FAT32格式了)SD卡能 ...…

查看全部问答>

串口发送通了 但是始终接收不到数据

        int tmp,i,j;         int receiv,send=0x30;         *ULCON0=0x03;         *UCON0=0x09;         *UBRDIV0=0x280;   ...…

查看全部问答>

一方案打算用FSMC控制彩屏..想请教

从原理上来说..如果用FSMC驱动彩屏..就是把它当作一个外部的存储器件来操作. 1)只有16bit数据线是不是代表每像素就是16bit的?2)需要LCD内带控制器的屏才可以..这样选型范围应该会缩小很多.而且会贵这种屏一般上批量的话能做到多少钱一片. ...…

查看全部问答>

STM8S103配置TIM1为输出比较模式不翻转

用的是103F的片子,想把TIM1设置成翻转输出比较模式,但端口不会发生翻转 配置程序如下: GPIO_Init(GPIOC, GPIO_PIN_6, GPIO_MODE_OUT_PP_HIGH_FAST); TIM1->CR1 &= 0xFE; // stop TIM1 TIM1->PSCRH = 0; TIM1->PSCRL = 0; ...…

查看全部问答>