stm32 AD模数转换[操作寄存器+库函数]
本例实现AD采样PB0口,使用串口输出PB0口电压值。PB0口接变阻器以改变调整电压。
- 00:PCLK2 2分频后作为ADC时钟 01:PCLK2 4分频后作为ADC时钟
10:PCLK2 6分频后作为ADC时钟 11:PCLK2 8分频后作为ADC时钟
设定各通道的采样时间ADCx->SMPR,该寄存器给每个通道3位来选择8种采样周期:000:1.5周期 100:41.5周期
- 001:7.5周期 101:55.5周期
- 010:13.5周期 110:71.5周期
- 011:28.5周期 111:239.5周期采样时间算法为: (采样周期+12.5)/分频后的时钟ADC采样得到的只是一个相对值,将 转换值/4096*参考电压 即可得到采样电压 这里的4096是因为stm32的adc为12位精度,表示参考电压时即为 2^12=4096User/main.c
#include <stm32f10x_lib.h>
#include “system.h”
#include “usart.h”
#include “adc.h”
#include “stdio.h”
#define LED1 PAout(4)
#define LED2 PAout(5)
#define VREF 3.3 //参考电压
void Gpio_Init(void);
int main(void)
{
u16 ADValue;
float temp;
Rcc_Init(9); //系统时钟设置
Usart1_Init(72,9600); //设置串口时钟和波特率
Adc1_Init(8,7); //使用8通道采样,采样时间系数为7(111),据手册可得采样时间为 (239.5+12.5)/12= 21 (us)
Gpio_Init();
while(1){
ADValue = Get_Adc(ADC_1,8);
temp = (float)VREF*(ADValue/4096); //ADC精度为12位精度,即达到 VREF电压时为 2^12 = 4096
printf("\r\n ADValue = %.2fv\r\n",temp);
LED2 = !LED2;
delay(100000); //延时100ms
}
}
void Gpio_Init(void)
{
RCC->APB2ENR|=1<<2; //使能PORTA时钟
RCC->APB2ENR|=1<<3; //使能PORTB时钟
GPIOA->CRL&=0xFF0FFFF0;
GPIOA->CRL|=0xFF3FFFF0; // PA0设置为模拟输入,PA4推挽输出
GPIOB->CRL&=0xFFFFFFF0;
GPIOB->CRL|=0xFFFFFFF0; // PB0设置为模拟输入
//USART1 串口I/O设置
GPIOA -> CRH&=0xFFFFF00F; //设置USART1 的Tx(PA.9)为第二功能推挽,50MHz;Rx(PA.10)为浮空输入
GPIOA -> CRH|=0x000008B0;
}
#include <stm32f10x_lib.h>
#include “adc.h”
//ADC1采样初始化
//独立工作模式
//参数说明:
// ADC_CH_x 选择使用通道(0~17),目前暂支持0~15通道
// ADC_CH_SMP 设定采样周期(0~7)
//采样周期算法:
void Adc1_Init(u8 ADC_CH_x,u8 ADC_CH_SMP)
{
RCC -> APB2ENR |= 1<<9; //开启ADC1时钟
RCC -> APB2RSTR |= 1<<9; //复位ADC1
RCC -> APB2RSTR &= ~(1<<9); //ADC1复位结束
RCC -> CFGR &= ~(3<<14); //分频因子清零
RCC -> CFGR |= 2<<14; //设定分频因数为2,PCLK2 6分频后作为ADC时钟
ADC1 -> CR1 &= 0xF0FFFF; //工作模式清零
ADC1 -> CR1 |= 0<<16; //设定为独立模式
ADC1 -> CR1 &= ~(1<<8); //非扫描工作模式
ADC1 -> CR2 &= ~(1<<1); //关闭连续转换
ADC1 -> CR2 &= ~(7<<17); //清除规则通道启动事件
ADC1 -> CR2 |= 7<<17; //设定规则通道启动事件为软件启动(SWSTART)
ADC1 -> CR2 |= 1<<20; //使用外部事件触发 SWSTART
ADC1 -> CR2 &= ~(1<<11); //设置对齐模式为右对齐
ADC1 -> SQR1 &= ~(0xF<<20); //清零规则序列的数量
ADC1 -> SQR1 |= 15<<20; //设置规则序列的数量为16
ADC1 -> SMPR2 &= 0x00000000; //清零通道采样时间
ADC1 -> SMPR1 &= 0xFF000000;
if(ADC_CH_x <= 9 ){
ADC1 -> SMPR2 |= 7<<(ADC_CH_x*3); //设置通道x采样时间,提高采样时间可以提高采样精度
}
if(ADC_CH_x > 9 ){
ADC1 -> SMPR1 |= 7<<((ADC_CH_x-10)*3);
}
ADC1 -> CR2 |= 1<<0; //开启AD转换
ADC1 -> CR2 |= 1<<3; //使能复位校准,由硬件清零
while((ADC1 -> CR2)& (1<<3)); //等待校准结束
ADC1 -> CR2 |= 1<<2; //开启AD校准,由硬件清零
while((ADC1 -> CR2)& (1<<2)); //等待校准结束
}
//取得数模转换的值
//参数说明:(参数定义于adc.h)
// ADC_x (0~3),选择数模转换器
// ADC_CH_x (0~15),选择通道
u16 Get_Adc(u8 ADC_x,u8 ADC_CH_x)
{
u16 data = 0;
switch(ADC_x)
{
case 1 : {
ADC1 -> SQR3 &= 0xFFFFFFE0; //清除通道选择
ADC1 -> SQR3 |= ADC_CH_x; //选择通道
ADC1 -> CR2 |= 1<<22; //开启AD转换
while(!(ADC1 -> SR & 1<<1)); //等待转换结束
data = ADC1->DR;
break;
}
case 2 : {break;}
case 3 : {break;}
}
return data;
}
#include <stm32f10x_lib.h>
#define ADC_1 0x01
#define ADC_2 0x02
#define ADC_3 0x03
void Adc1_Init(u8 ADC_CH_x,u8 ADC_CH_SMP);
u16 Get_Adc(u8 ADC_x,u8 ADC_CH_x);
#include “stm32f10x.h”
#include “stdio.h”
#define PRINTF_ON 1
#define VREF 3.3 // 参考电压
void RCC_Configuration(void);
void GPIO_Configuration(void);
void USART_Configuration(void);
void ADC_Configuration(void);
int main(void)
{
float ADValue = 0.00;
u32 delayTime = 0;
RCC_Configuration();
GPIO_Configuration();
USART_Configuration();
ADC_Configuration();
while(1)
{
if(delayTime++ >=2000000)
{
delayTime = 0;
ADValue = VREF*ADC_GetConversionValue(ADC1)/0x0fff;
printf("\r\n ADValue = %.2fv\r\n",ADValue);
}
}
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA , &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA , &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA , &GPIO_InitStructure);
}
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
RCC_ADCCLKConfig(RCC_PCLK2_Div4); //配置ADC时钟分频
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1,&ADC_InitStructure);
ADC_RegularChannelConfig(ADC1,ADC_Channel_8,1,ADC_SampleTime_55Cycles5);
ADC_Cmd(ADC1,ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}
void RCC_Configuration(void)
{
/ 定义枚举类型变量 HSEStartUpStatus /
ErrorStatus HSEStartUpStatus;
/* 复位系统时钟设置*/
RCC_DeInit();
/* 开启HSE*/
RCC_HSEConfig(RCC_HSE_ON);
/* 等待HSE起振并稳定*/
HSEStartUpStatus = RCC_WaitForHSEStartUp();
/* 判断HSE起是否振成功,是则进入if()内部 */
if(HSEStartUpStatus == SUCCESS)
{
/* 选择HCLK(AHB)时钟源为SYSCLK 1分频 */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/* 选择PCLK2时钟源为 HCLK(AHB) 1分频 */
RCC_PCLK2Config(RCC_HCLK_Div1);
/* 选择PCLK1时钟源为 HCLK(AHB) 2分频 */
RCC_PCLK1Config(RCC_HCLK_Div2);
/* 设置FLASH延时周期数为2 */
FLASH_SetLatency(FLASH_Latency_2);
/* 使能FLASH预取缓存 */
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
/* 选择锁相环(PLL)时钟源为HSE 1分频,倍频数为9,则PLL输出频率为 8MHz * 9 = 72MHz */
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
/* 使能PLL */
RCC_PLLCmd(ENABLE);
/* 等待PLL输出稳定 */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
/* 选择SYSCLK时钟源为PLL */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* 等待PLL成为SYSCLK时钟源 */
while(RCC_GetSYSCLKSource() != 0x08);
}
/* 打开APB2总线上的GPIOA时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOB|RCC_APB2Periph_ADC1, ENABLE);
//RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
}
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStructure;
USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
USART_ClockInit(USART1 , &USART_ClockInitStructure);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
USART_Init(USART1,&USART_InitStructure);
USART_Cmd(USART1,ENABLE);
}
#if PRINTF_ON
int fputc(int ch,FILE *f)
{
USART_SendData(USART1,(u8) ch);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
return ch;
}
#endif