利用DMA接收和发送不定长数据例程


前言

DMA(Direct Memory Access:直接存储器存取)在无须 CPU 干预的情况下,可实现外设与存储器或存储器与存储器之间数据的直接传输,从而节省 CPU 资源来做其他操作。
以下例程以APM32F030x6x8为主控芯片,利用DMA接收和发送不定长的数据,其他ARM内核的单片机都大同小异。


一、串口初始化

void Uart1Init(u32 baud_rate)
{
	GPIO_Config_T gpioConfig;
	USART_Config_T usartConfigStruct;

	/** Enable GPIO clock */
	RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);
	/** Enable COM1 or COM2 clock */
	RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_USART1);

	/** Connect PXx to USARTx_Tx */
	GPIO_ConfigPinAF(GPIOA,GPIO_PIN_SOURCE_9,GPIO_AF_PIN1);
	/** Connect PXx to USARRX_Rx */
	GPIO_ConfigPinAF(GPIOA,GPIO_PIN_SOURCE_10,GPIO_AF_PIN1);

	/** Configure USART Tx as alternate function push-pull */
	gpioConfig.mode = GPIO_MODE_AF;
	gpioConfig.pin = GPIO_PIN_9;
	gpioConfig.speed = GPIO_SPEED_50MHz;
	gpioConfig.outtype = GPIO_OUT_TYPE_PP;
	gpioConfig.pupd = GPIO_PUPD_PU;
	GPIO_Config(GPIOA, &gpioConfig);

	/** Configure USART Rx as input floating */
	gpioConfig.pin  = GPIO_PIN_10;
	GPIO_Config(GPIOA, &gpioConfig);


	/** BaudRate baud   */
	usartConfigStruct.baudRate = baud_rate;
	/** Receive and transmit enabled  */
	usartConfigStruct.mode     = USART_MODE_TX_RX;
	/** Hardware flow control disabled (RTS and CTS signals)   */
	usartConfigStruct.hardwareFlowCtrl = USART_FLOW_CTRL_NONE;
	/** No parity  */
	usartConfigStruct.parity   = USART_PARITY_NONE;
	/** One Stop Bit  */
	usartConfigStruct.stopBits =  USART_STOP_BIT_1;
	/** Word Length = 8 Bits  */
	usartConfigStruct.wordLength = USART_WORD_LEN_8B;
	/** USART_Config  */
	USART_Config(USART1, &usartConfigStruct);

	/** Enable USART_Interrupt*/
	USART_EnableInterrupt(USART1,USART_INT_IDLEIE);
	NVIC_EnableIRQRequest(USART1_IRQn,2);
    
	/** Enable USART */
	USART_Enable(USART1);
}

以上代码将串口1初始化,并使能串口接收空闲中断。

二、DMA初始化

1.串口接收DMA初始化

void DMA_Rx_Init(uint32_t* RxBuf,uint32_t buf_size)
{
    /** Enable DMA clock */
    RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA1);
    /** DMA Configure */
    DMA_Config_T dmaConfig;
    /** size of buffer*/
    dmaConfig.bufferSize = buf_size;
    /** set memory Data Size*/
    dmaConfig.memoryDataSize = DMA_MEMORY_DATASIZE_BYTE;
    /** Set peripheral Data Size*/
    dmaConfig.peripheralDataSize = DMA_PERIPHERAL_DATASIZE_BYTE;
    /** Enable Memory Address increase*/
    dmaConfig.memoryInc = DMA_MEMORY_INC_ENABLE;
    /** Disable Peripheral Address increase*/
    dmaConfig.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;
    /** Reset Circular Mode*/
    dmaConfig.circular = DMA_CIRCULAR_DISABLE;
    /** Disable M2M*/
    dmaConfig.memoryTomemory = DMA_M2M_DISABLE;
    /** set priority*/
    dmaConfig.priority = DMA_PRIORITY_LEVEL_HIGHT;
    /** read from memory*/
    dmaConfig.direction = DMA_DIR_PERIPHERAL;
    /** Set memory Address*/
    dmaConfig.memoryAddress = (uint32_t)RxBuf;
    /** Set Peripheral Address*/
    dmaConfig.peripheralAddress = (uint32_t)&USART1->RXDATA;

    DMA_Config(DMA1_CHANNEL_3, &dmaConfig);
    /** Clear DMA TF flag*/
    DMA_ClearIntFlag(DMA1_INT_FLAG_TF3);
    /** Enable DMA Interrupt*/
    DMA_EnableInterrupt(DMA1_CHANNEL_3, DMA_INT_TFIE);
    NVIC_EnableIRQRequest(DMA1_CH2_3_IRQn, 2);
   
    USART_EnableDMA(USART1, USART_DMA_REQUEST_RX);             
    DMA_Enable(DMA1_CHANNEL_3);                                 
}

2.串口发送DMA初始化

void DMA_Tx_Init(uint32_t* TxBuf)
{
    /** Enable DMA clock */
    RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA1);
    /** DMA Configure */
    DMA_Config_T dmaConfig;
    /** size of buffer*/
    dmaConfig.bufferSize = 128;
    /** set memory Data Size*/
    dmaConfig.memoryDataSize = DMA_MEMORY_DATASIZE_BYTE;
    /** Set peripheral Data Size*/
    dmaConfig.peripheralDataSize = DMA_PERIPHERAL_DATASIZE_BYTE;
    /** Enable Memory Address increase*/
    dmaConfig.memoryInc = DMA_MEMORY_INC_ENABLE;
    /** Disable Peripheral Address increase*/
    dmaConfig.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;
    /** Reset Circular Mode*/
    dmaConfig.circular = DMA_CIRCULAR_DISABLE;
    /** Disable M2M*/
    dmaConfig.memoryTomemory = DMA_M2M_DISABLE;
    /** set priority*/
    dmaConfig.priority = DMA_PRIORITY_LEVEL_HIGHT;
    /** read from memory*/
    dmaConfig.direction = DMA_DIR_MEMORY;                 
    /** Set memory Address*/
    dmaConfig.memoryAddress = (uint32_t)TxBuf;
    /** Set Peripheral Address*/
    dmaConfig.peripheralAddress = (uint32_t)&USART1->TXDATA;

    DMA_Config(DMA1_CHANNEL_2, &dmaConfig);
    /** Clear DMA TF flag*/
    DMA_ClearIntFlag(DMA1_INT_FLAG_TF2);
    /** Enable DMA Interrupt*/
    DMA_EnableInterrupt(DMA1_CHANNEL_2, DMA_INT_TFIE);
    NVIC_EnableIRQRequest(DMA1_CH2_3_IRQn, 2);
   
    USART_EnableDMA(USART1, USART_DMA_REQUEST_TX);             
    DMA_Disable(DMA1_CHANNEL_4);                                
}

3. 主程序代码


char UartRxBuf[128];      
char UartTxBuf[128];

//DMA串口发送函数
void Uart_DMA_Tx(u8 *dat,u16 len)
{ 
    memcpy(UartTxBuf,dat,len);    
    DMA_Disable(DMA1_CHANNEL_2);
    DMA_SetDataNumber(DMA1_CHANNEL_2,len);  //设置DMA传输的长度,只有在DMA disable的情况下才能设置
    DMA_Enable(DMA1_CHANNEL_2);
}

//DMA串口接收函数
void Uart_DMA_Rx()
{
	//将接收到数据,再次发送出来
	//由于DMA的传输计数是递减式的,因此总数减去当前值,就是当前接收到的数量
    Uart_DMA_Tx(UartRxBuf,128-DMA_ReadDataNumber(DMA1_CHANNEL_3));
    
    memset(UartRxBuf,0,sizeof(UartRxBuf));
    DMA_Disable(DMA1_CHANNEL_3);
    DMA_SetDataNumber(DMA1_CHANNEL_3,128);
    DMA_Enable(DMA1_CHANNEL_3);
}

//串口接收空闲中断
void USART1_IRQHandler(void)
{
    USART_ClearStatusFlag(USART1, USART_FLAG_IDLEF);
    Uart_DMA_Rx();
}

void main()
{
	Uart1Init(115200;
	DMA_Tx_Init((uint32_t*)UartTxBuf);
	DMA_Rx_Init((uint32_t*)UartRxBuf);
	
	while1{
	
	}
}

4. 实验结果

在这里插入图片描述
串口输入回环输出

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值