欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[寄存器版本]STM32F407 独立ADC-DMA-双通道

程序员文章站 2022-06-09 10:50:54
...

STM32F407 独立ADC-DMA-双通道之寄存器版本

最近自学了ADC采样实验,但是发现基本都是库函数版本的,因此就想着把自己写的寄存器版本的代码写出来,顺便复习一下。

功能

使用ADC1的通道5和通道9,采集电压,并通过串口打印出来。

开发环境

Keil uVision5编辑器
FlyMcu下载器
XCOM V2.6串口调试助手

ADC简介

接上篇独立模式ADC+DMA+单通道【寄存器版本】

时钟选择:

ADC时钟挂载在APB2总线上,可以配置ADC通用寄存器进行分频,但是注意分频后不要超过36M。

通道选择:

每个ADC有18个通道,其中外部通道有16个,可以分为2组:规则通道和注入通道。

代码编写

main.c函数如下:

extern u16 ADC_ConvertedValue[2];
float ADC_Vol[2] = {0,0};

int main(void)
{
   Stm32_Clock_Init(336,8,2,7);
   delay_Init(168);
   uart_Init(84,115200);
   Led_Init();
   Dma2_Init();
   Adc1_Init();

  while(1)
  {
     LED0 = !LED0;
     
      ADC_Vol[0] = (float)ADC_ConvertedValue[0]/4096(float)3.3;
      ADC_Vol[1] = (float)ADC_ConvertedValue[1]/4096(float)3.3;

     printf("\r\n ADC_ConvertedValue[0] = 0x%04x \r\n",ADC_ConvertedValue[0]);
     printf("\r\n ADC_ConvertedValue[1] =  0x%04x \r\n",ADC_ConvertedValue[1]);
     printf("\r\n ADC_Vol[0] = %f V \r\n",ADC_Vol[0]);
     printf("\r\n ADC_Vol[1] = %f V \r\n",ADC_Vol[1]);
     delay_ms(1000);
  }
}

led.c函数如下:

void Led_Init(void)
{
  RCC->AHB1ENR |= 1<<5;
  GPIO_Set(GPIOF,PIN9,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_2M,GPIO_PUPD_PU);
  LED0 = 1;
}

adc.c函数如下:

void ADC1_Init(void)
{
  ADC1_Io_Init();
  ADC1_Config();
}

void ADC1_Io_Init(void)
{
  RCC->AHB1ENR |= 1<<0;//使能GPIOA时钟
  RCC->AHB1ENR |= 1<<1;//使能GPIOB时钟
  GPIO_Set(GPIOA,PIN5,GPIO_MODE_AIN,0,0,GPIO_PUPD_NONE);
  GPIO_Set(GPIOB,PIN1,GPIO_MODE_AIN,0,0,GPIO_PUPD_NONE);
}

void ADC1_Config(void)
{
   RCC->APB2ENR |= 1<<8; 
   
   ADC->CCR |= 1<<16;//4分频
   ADC->CCR &= ~(31<<0);//独立模式

   ADC1->CR1 &= ~(3<<24);//12位分辨率
   ADC1->CR1 |= 1<<8;//使能扫描模式
   
   ADC1->CR2 &= ~(1<<11);//数据右对齐
   ADC1->CR2 &= ~(1<<1);//单次转换模式

   ADC1->SMPR2 |= 7<<3*5;//通道5采样时间
   ADC1->SMPR2 |= 7<<3*9;//通道9采样时间
   ADC1->SQR1 |= 1<<20;//2次转换
   ADC1->SQR3 |= 5<<0;//通道5第一次转换
   ADC1->SQR3 |= 9<<5;//通道9第二次转换
   

   ADC1->CR2 |= 1<<9;//只要发生数据转换且DMA = 1,便会发出DMA请求
   ADC1->CR2 |= 1<<8;//使能DMA模式 
    
   ADC1->CR2 |= 1<<0;//使能ADC
   ADC1->CR2 |= 1<<30;//开始转换规则通道
}

dma.c函数如下:

u16 ADC_ConvertedValue[2] = {0,0}; 
void Dma2_Init(void)
{
   RCC->AHB1ENR |= 1<<22;//使能DMA2时钟

  DMA2_Stream0->CR &= ~(1<<0);//禁止数据流
  while(DMA2_Stream0->CR & 0X01);//等待DMA2可配置
  DMA2->LIFCR |= 0X3D<<0;//清空数据流上的所有中断标志

 DMA2_Stream0->PAR |= (u32)&ADC1->DR;//外设地址
 DMA2_Stream0->M0AR |= (u32)ADC_ConvertedValue;//
 DMA2_Stream0->NDTR |= 2;//要传输的数据项的总数
 DMA2_Stream0->CR &= ~(7<<25);//选择通道0
 DMA2_Stream0->CR |= 1<<16;//优先级 中
 DMA2_Stream0->FCR &= ~(1<<2);//使能直接模式
 DMA2_Stream0->CR |= 1<<13;//存储器数据大小 半字 16位(MSIZE)
 DMA2_Stream0->CR |= 1<<11;//外设数据大小 半字 16位 (PSIZE)
 DMA2_Stream0->CR |= (1<<10);//每次数据传输后,存储器地址指针递增(MSIZE)
 DMA2_Stream0->CR &= ~(1<<9);//外设地址指针固定
 DMA2_Stream0->CR |= 1<<8;//使能循环模式
 DMA2_Stream0->CR &= ~(3<<6);//数据传输方向  外设到存储器
	
 DMA2_Stream0->CR |= 1<<0;//使能数据流
}

下载验证

[寄存器版本]STM32F407 独立ADC-DMA-双通道
通道5采集0V电压,通道9采集3.3V电压。

相关标签: 嵌入式 单片机