一、STM32的ADC
ADC的主要参数:采样时间和分辨率
STM32的ADC的最高采样速率为1us;
STM32的分辨率为12位,采样后的值为0-4095。
ADC的初始化代码
#include "adc1.h"
#include "sys.h"
#include
void ADC1_Regular_Init(void)
{
//光敏电阻初始化
RCC->APB2ENR |= 1<<3;
GPIOB->CRL &= 0XFFFFFFF0;
//ADC时钟配置
RCC->APB2ENR |= 1<<9;
RCC->CFGR &= ~(3<<14);
RCC->CFGR |= 2<<14;
//ADC复位
RCC->APB2RSTR |= 1<<9;
RCC->APB2RSTR &= ~(1<<9);
//ADC相关配置
ADC1->CR1 &= ~(0XF<<16); //设置ADC1为独立模式
ADC1->CR1 |= 1<<8; //开启扫描模式
ADC1->CR2 |= 1<<23; //开启内部温度传感器
ADC1->CR2 |= 1<<20; //使用外部事件触发
ADC1->CR2 |= 7<<17; //选择SWSTART为外部触发源
ADC1->CR2 &= ~(1<<11); //数据右对齐
ADC1->CR2 |= 1<<8; //使用DMA
ADC1->CR2 &= ~(1<<1); //开启单次转换
ADC1->SQR1 &= ~(0xf<<20); //设置规则通道转换的数目
ADC1->SQR1 |= 1<<20;
ADC1->SQR3 &= 0XFFFFFC00;
ADC1->SQR3 |= 8;
ADC1->SQR3 |= 16<<5;
ADC1->SMPR2 |= 7<<24; //设置采样时间
ADC1->SMPR1 |= 7<<18; //设置采样时间
//校准
ADC1->CR2 |= 1<<0; // 开启ADC1
ADC1->CR2 |= 1<<3; //初始化校准寄存器
while(ADC1->CR2 & 1<<3);
ADC1->CR2 |= 1<<2; //开始校准
while(ADC1->CR2 & 1<<2);
}
uint16_t ADC1_GetValue(uint8_t CHx)
{
//设置ADC1的通道X的采样周期
if(CHx>=10)
{
//设置采样周期为239.5周期
ADC1->SMPR1 &= ~(7<<(CHx-10)*3);
ADC1->SMPR1 |= 7<<((CHx-10)*3);
}
else
{
//设置采样周期为239.5周期
ADC1->SMPR2 &= ~(7<<(CHx*3));
ADC1->SMPR2 |= 7<<(CHx*3);
}
//设置ADC1的CHx通道第一个转换并设置序列号
ADC1->SQR3 &= ~(0x1f<<0);
ADC1->SQR3 |= (CHx & 0X1F);
ADC1->CR2 |= 1<<22; //开始转换规则通道
while(!(ADC1->SR & 1<<1)); //等待转换完成
return ADC1->DR; //返回转换后的AD值
}
void ADC1_Injected_Init(void)
{
//初始化温度传感器
RCC->APB2ENR |= 1<<3;
GPIOB->CRL &= 0XFFFFFFF0;
//ADC1时钟配置
RCC->APB2ENR |= 1<<9;
RCC->CFGR &= ~(3<<14);
RCC->CFGR |= 2<<14;
//ADC复位
RCC->APB2RSTR |= 1<<9;
RCC->APB2RSTR &= ~(1<<9);
//ADC1相关配置
ADC1->CR1 &= ~(0XF<<16); //独立模式
ADC1->CR1 |= 1<<10; //开启自动的注入通道组转换
ADC1->CR1 |= 1<<8; //开启扫描模式
ADC1->CR1 |= 1<<7; //允许JEOC中断
CM3_NVIC_SetPriority(ADC1_2_IRQn,1,1);
ADC1->CR2 |= 1<<23; //启用温度传感器
ADC1->CR2 |= 1<<15; //使用外部事件启动转换
ADC1->CR2 |= 7<<12; //选择注入通道启动的事件为JSWSTART
ADC1->CR2 &= ~(1<<11); //数据右对齐
ADC1->CR2 &= ~(1<<8); //不开启DMA
ADC1->CR2 &= ~(1<<1); //单次转换
//设置CH8的采样时间位239.5周期
ADC1->SMPR2 |= 7<<24;
//设置CH16的采样时间为239.5周期
ADC1->SMPR1 |= 7<<18;
ADC1->JSQR |= 1<<20; //2个注入转换通道
//设置CH8第1个转换
ADC1->JSQR |= 8<<10;
ADC1->JSQR |= 16<<15;
//复位校准
ADC1->CR2 |= 1<<0; //开启ADC1
ADC1->CR2 |= 1<<3; //复位校准
while(ADC1->CR2 & 1<<3);
ADC1->CR2 |= 1<<2; //AD校准
while(ADC1->CR2 & 1<<2);
}
void ADC1_2_IRQHandler(void)
{
u16 Light;
u16 AD;
float VSENSE; //温度AD值对应的电压值
float V25 = 1.43; //参考值
float Avg_Slope = 0.0043; //平均斜率
float Temp;
if(ADC1->SR & 1<<2) //JEOC
{
Light = ADC1->JDR1;
AD = ADC1->JDR2; //CPU温度
printf("AD = %d\n",AD);
VSENSE = AD / 4096.0 * 3.3;
//温度(°C) = {(V25 - VSENSE) / Avg_Slope} + 25
Temp = ((V25 - VSENSE) / Avg_Slope) + 25;
printf("light = %d, Temp = %.1f\n", Light, Temp);
ADC1->SR &= ~(1<<2); //清除JEOC
}
}
DMA初始化
#include "dma.h"
#include "delay.h"
void DMA1_P2M_Init(uint32_t src,uint32_t des)
{
RCC->AHBENR |= 1<<0; //开启DAM1的时钟
Delay_ms(10);
DMA1_Channel1->CCR &= ~(1<<14); //非存储器到存储器模式
DMA1_Channel1->CCR |= 3<<12; //优先级最高
DMA1_Channel1->CCR &= ~(3<<10); //设置存储器数据宽度为16位
DMA1_Channel1->CCR |= 1<<10;
DMA1_Channel1->CCR |= 1<<8; //设置外设数据位宽度16位
DMA1_Channel1->CCR |= 1<<7; //存储器地址增量模式
DMA1_Channel1->CCR &= ~(1<<6); //不开启外设地址增量模式
DMA1_Channel1->CCR &= ~(1<<5); //不开启循环模式
DMA1_Channel1->CCR &= ~(1<<4); //数据传输方向位外设到存储器
DMA1_Channel1->CPAR = src;
DMA1_Channel1->CMAR = des;
}
void DMA1_StartUp(uint16_t num)
{
DMA1_Channel1->CCR &= ~(1<<0); //关闭传输
DMA1_Channel1->CNDTR = num; //传输数量
DMA1_Channel1->CCR |= 1<<0; //开始传输
}
主函数
#include "stm32f10x.h" // Device header
#include "led.h"
#include "Delay.h"
#include "Key.h"
#include "exti.h"
#include "BEEP.h"
#include "Usart3.h"
#include "Timer.h"
#include "string.h"
#include "usart.h"
#include "ESP8266.h"
#include "OLED.h"
#include "RTC.h"
#include "ADC1.h"
#include "dma.h"
uint8_t KeyNum ;
int main(void)
{
uint16_t buff[2];
Led_Init();
BEEP_Init();
Key_Init();
USART1_Init(115200);
Timer1_Init(729,10*1000);
DMA1_P2M_Init((uint32_t)&(ADC1->DR),(uint32_t)buff);
DMA1_StartUp(2);
ADC1_Regular_Init();
ADC1->CR2 |= 1<<22;
BEEP_ON;
Delay_ms(50);
BEEP_OFF;
while(1)
{
if(DMA1->ISR & 1<<1)
{
printf("ad[0]=%d, ad[1]=%d\n", buff[0], buff[1]);
DMA1->IFCR |= 1<<1;
DMA1_StartUp(2);
ADC1->CR2 |= 1<<22;
}
}
}