stm32g4 adc dma 串口发送
时间: 2023-09-10 13:07:27 浏览: 341
AN5346_STM32G4 ADC使用提示和建议.pdf
你可以使用STM32G4系列微控制器的DMA(直接内存访问)功能来实现ADC数据的传输和串口发送。DMA可以在ADC转换完成后自动将数据传输到内存,然后你可以使用串口发送这些数据。
下面是一个基本的示例代码,演示了如何使用ADC和DMA以及串口发送数据:
```c
#include "stm32g4xx.h"
// 定义ADC通道和数据缓冲区
#define ADC_CHANNEL ADC_CHANNEL_1
#define ADC_BUFFER_SIZE 100
uint16_t adcBuffer[ADC_BUFFER_SIZE];
void ADC_DMA_Init(void)
{
// 使能DMA1的时钟
RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
// 配置DMA的通道和流
DMA1_Channel1->CCR &= ~DMA_CCR_EN; // 关闭DMA通道1
while(DMA1_Channel1->CCR & DMA_CCR_EN); // 等待DMA通道1关闭
DMA1_Channel1->CCR = 0; // 清除控制寄存器
DMA1_Channel1->CCR |= DMA_CCR_MINC; // 内存递增模式
DMA1_Channel1->CCR |= DMA_CCR_MSIZE_0; // 内存数据宽度为16位
DMA1_Channel1->CCR |= DMA_CCR_PSIZE_0; // 外设数据宽度为16位
DMA1_Channel1->CCR |= DMA_CCR_CIRC; // 循环模式
DMA1_Channel1->CCR |= DMA_CCR_TCIE; // 传输完成中断使能
DMA1_Channel1->CPAR = (uint32_t)(&(ADC1->DR)); // 外设地址为ADC数据寄存器
DMA1_Channel1->CMAR = (uint32_t)adcBuffer; // 内存地址为ADC数据缓冲区
DMA1_Channel1->CNDTR = ADC_BUFFER_SIZE; // 数据传输长度
NVIC_SetPriority(DMA1_Channel1_IRQn, 0); // 设置DMA中断优先级
NVIC_EnableIRQ(DMA1_Channel1_IRQn); // 使能DMA中断
// 配置ADC
RCC->AHB2ENR |= RCC_AHB2ENR_ADC12EN; // 使能ADC时钟
ADC1->CFGR = ADC_CFGR_CONT; // 连续转换模式
ADC1->SQR1 = (0 << ADC_SQR1_L_Pos); // 转换序列长度为1个转换
ADC1->SQR1 |= (ADC_CHANNEL << ADC_SQR1_SQ1_Pos); // 设置转换通道
ADC1->CR = ADC_CR_ADEN; // 打开ADC和温度传感器
while(!(ADC1->ISR & ADC_ISR_ADRDY)); // 等待ADC就绪
}
void USART_Init(void)
{
// 使能USART2的时钟
RCC->APB1LENR |= RCC_APB1LENR_USART2EN;
// 配置GPIO引脚
GPIOA->MODER &= ~(GPIO_MODER_MODE2_0 | GPIO_MODER_MODE2_1); // PA2设置为复用功能
GPIOA->MODER |= (GPIO_MODER_MODE2_1);
GPIOA->AFR[0] &= ~(GPIO_AFRL_AFSEL2); // 将PA2的复用功能设置为USART2
GPIOA->AFR[0] |= (GPIO_AFRL_AFSEL2_0 | GPIO_AFRL_AFSEL2_1 | GPIO_AFRL_AFSEL2_2);
// 配置USART2
USART2->CR1 &= ~(USART_CR1_UE); // 关闭USART2
while(USART2->CR1 & USART_CR1_UE); // 等待USART2关闭
USART2->BRR = 0x1A0; // 波特率设置为115200 @30MHz
USART2->CR1 |= (USART_CR1_TE | USART_CR1_RE); // 使能发送和接收
USART2->CR1 |= USART_CR1_UE; // 打开USART2
}
void DMA1_Channel1_IRQHandler(void)
{
if (DMA1->ISR & DMA_ISR_TCIF1) // 判断是否是传输完成中断
{
DMA1->IFCR = DMA_IFCR_CTCIF1; // 清除传输完成中断标志
// 在这里可以对adcBuffer中的数据进行处理
// 比如发送到串口
for (int i = 0; i < ADC_BUFFER_SIZE; i++)
{
while (!(USART2->ISR & USART_ISR_TXE)); // 等待发送缓冲区为空
USART2->TDR = adcBuffer[i]; // 发送数据到USART2
}
}
}
int main(void)
{
ADC_DMA_Init();
USART_Init();
ADC1->CR |= ADC_CR_ADSTART; // 启动ADC转换
while (1)
{
// 主循环中可以添加其他的任务或者代码
// ADC数据会在后台自动转换和传输到串口
}
}
```
这段代码通过配置DMA通道将ADC数据传输到内存中的缓冲区,然后通过串口发送这些数据。你可以根据需求修改代码中的ADC通道、数据缓冲区大小以及波特率等参数。同时,你还可以在主循环中添加其他的任务或代码,ADC数据的转换和传输将在后台进行。
希望这个示例能对你有所帮助!如有任何疑问,请随时提问。
阅读全文