文章目录
在很长的一段时间里我在项目中都是使用寄存器方式
一、寄存器列表
__IO uint32_t SR;/!< ADC状态寄存器,地址偏移量:0x00 /
__IO uint32_t CR1;/!< ADC控制寄存器1,地址偏移量:0x04 /
__IO uint32_t CR2;/!< ADC控制寄存器2,地址偏移量:0x08 /
__IO uint32_t SMPR1;/!< ADC采样时间寄存器1,地址偏移量:0x0C /
__IO uint32_t SMPR2;/!< ADC采样时间寄存器2,地址偏移量:0x10 /
__IO uint32_t JOFR1;/!< ADC注入通道数据偏移寄存器1,地址偏移:0x14 /
__IO uint32_t JOFR2;/!< ADC注入通道数据偏移寄存器2,地址偏移:0x18 /
__IO uint32_t JOFR3;/!< ADC注入通道数据偏移寄存器3,地址偏移:0x1C /
__IO uint32_t JOFR4;/!< ADC注入通道数据偏移寄存器4,地址偏移:0x20 /
__IO uint32_t HTR;/!< ADC看门狗高阈值寄存器,地址偏移量:0x24 /
__IO uint32_t LTR;/!< ADC看门狗下门限寄存器,地址偏移量:0x28 /
__IO uint32_t SQR1;/!< ADC常规序列寄存器1,地址偏移量:0x2C /
__IO uint32_t SQR2;/!< ADC常规序列寄存器2,地址偏移量:0x30 /
__IO uint32_t SQR3;/!< ADC常规序列寄存器3,地址偏移量:0x34 /
__IO uint32_t JSQR;/!< ADC注入序列寄存器,地址偏移量:0x38/
__IO uint32_t JDR1;/*!< ADC注入数据寄存器1,地址偏移量:0x3C /
__IO uint32_t JDR2;/!< ADC注入数据寄存器2,地址偏移量:0x40 /
__IO uint32_t JDR3;/!< ADC注入数据寄存器3,地址偏移量:0x44 /
__IO uint32_t JDR4;/!< ADC注入数据寄存器4,地址偏移量:0x48 /
__IO uint32_t DR;/!< ADC常规数据寄存器,地址偏移量:0x4C */
二、示例代码
//初始化
s32 Dev_Adc_Init(uint8_t ch)
{
GPIO_InitTypeDef GPIO_InitStruct;
/**ADC1 GPIO Configuration
PC2 ------> ADC1_IN12
PC3 ------> ADC1_IN13
/
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
RCC->APB2ENR|=1<<9; //ADC1时钟使能
RCC->APB2RSTR|=1<<9; //ADC1复位
RCC->APB2RSTR&=~(1<<9);//复位结束
RCC->CFGR&=~(3<<14); //分频因子清零
//SYSCLK/DIV2=12M ADC时钟设置为12M,ADC最大时钟不能超过14M!
//否则将导致ADC准确度下降!
RCC->CFGR|=2<<14;
ADC1->CR1&=0XF0FFFF; //工作模式清零
ADC1->CR1|=0<<16; //独立工作模式
ADC1->CR1&=~(1<<8); //非扫描模式
ADC1->CR2&=~(1<<1); //单次转换模式
ADC1->CR2&=~(7<<17);
ADC1->CR2|=7<<17; //软件控制转换
ADC1->CR2|=1<<20; //使用用外部触发(SWSTART)!!! 必须使用一个事件来触发
ADC1->CR2&=~(1<<11); //右对齐
ADC1->SQR1&=~(0XF<<20);
ADC1->SQR1|=0<<20; //1个转换在规则序列中 也就是只转换规则序列1
//设置通道1的采样时间
ADC1->SMPR2&=~(7<<(3ch)); //通道1采样时间清空
ADC1->SMPR2|=7<<(3*ch); //通道1 239.5周期,提高采样时间可以提高精确度
ADC1->CR2|=1<<0; //开启AD转换器
ADC1->CR2|=1<<3; //使能复位校准
while(ADC1->CR2&1<<3); //等待校准结束
//该位由软件设置并由硬件清除。在校准寄存器被初始化后该位将被清除。
ADC1->CR2|=1<<2; //开启AD校准
while(ADC1->CR2&1<<2); //等待校准结束
}
//获得ADC1某个通道的值
//ch:通道值 0~16
//返回值:转换结果
uint32_t Get_Adc(uint8_t ch)
{
//设置转换序列
ADC1->SQR3&=0XFFFFFFE0;//规则序列1 通道ch
ADC1->SQR3|=ch;
ADC1->CR2|=1<<22; //启动规则转换通道
while(!(ADC1->SR&1<<1));//等待转换结束
return ADC1->DR; //返回adc值
}
//获取通道ch的转换值,取times次,然后平均
//ch:通道编号
//times:获取次数
//返回值:通道ch的times次转换结果平均值
uint32_t Get_Adc_Average(uint8_t ch,uint8_t times)
{
uint32_t temp_val=0;
uint8_t t;
for(t=0;t<times;t++)
{
temp_val+=Get_Adc(ch);
//delay_ms(5);
}
return temp_val/times;
}
初始化后在程序中调用Get_Adc_Average进行采样值读取
三、总结
寄存器方式读取ADC数据是最基本的读取方式。在这种方式下,CPU直接通过读取ADC的寄存器来获取转换结果。具体来说,当ADC完成一次转换后,转换结果会被存储在特定的寄存器中,程序通过读取这些寄存器的内容来获取转换后的数字值。
优点:
简单直观:操作过程简单,易于理解和实现。
灵活性高:可以根据需要随时读取ADC数据,不受DMA传输的限制。
缺点:
CPU占用率高:每次读取数据都需要CPU的参与,增加了CPU的负担。
效率低:在高速数据采集场景下,CPU可能无法及时响应,导致数据丢失或处理延迟。
标签:__,寄存器,STM32,ADC,IO,ADC1,uint32 From: https://blog.csdn.net/u013050118/article/details/143004182