当前位置: 首页 > article >正文

STM32 7-8

目录

ADC

AD单通道

AD多通道

DMA

DMA转运数据

DMA+AD多通道


ADC

AD单通道

AD.c

#include "stm32f10x.h"                  // Device header

/**
  * @brief  初始化AD所需要的所有设备
  * @param  无
  * @retval 无
  */
void AD_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
    
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADCCLK为六分频
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
   
    ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1, ADC_SampleTime_55Cycles5);//配置输入通道
    //所选ADC设备,指定ADC通道,规则组序列器中的次序,指定通道采样时间(更快就选小参数,更稳定就选大参数)
   
    //初始化ADC
    ADC_InitTypeDef ADC_InitStructure;
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC工作模式
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据对齐
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//外部触发转换选择

    //单通道单次转换非扫描模式    
    //单通道连续转换,非扫描模式
    
    ADC_InitStructure.ADC_NbrOfChannel = 1;//通道数目
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;//扫描转换模式
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//非连续转换模式
    //ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//连续转换模式
    ADC_Init(ADC1,&ADC_InitStructure);
    
    ADC_Cmd(ADC1,ENABLE);//开启ADC1
    
    //进行ADC校准
    ADC_ResetCalibration(ADC1);//复位校准
    while(ADC_GetResetCalibrationStatus(ADC1) == SET);//等待复位校准完成
    ADC_StartCalibration(ADC1);//开始校准
    while(ADC_GetCalibrationStatus(ADC1) == SET);//等待校准完成
    
    //ADC_SoftwareStartConvCmd(ADC1,ENABLE);//开启软件触发转换
}

/**
  * @brief  获取AD所得值
  * @param  无
  * @retval  转化出来的数据量最大为4095
  */
uint16_t AD_GetValue(void)
{
    ADC_SoftwareStartConvCmd(ADC1,ENABLE);//开启软件触发转换
    while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//获取标志位状态(为Reset表示没有转换完成)
    //大约等待 (1 / 72MHz / 6) X (55.5 + 12.5) = 5.6us
    return ADC_GetConversionValue(ADC1);//调用后会自动清除EOC标志位
}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"

uint16_t ADValue;
float Voltage;

int main(void)
{
	OLED_Init();
	AD_Init();
	
    OLED_ShowString(1,1,"ADValue:");
    OLED_ShowString(2,1,"Voltage:0.00V");
	while(1)
	{
		ADValue = AD_GetValue();
        Voltage = (float)ADValue / 4095 * 3.3;
        
        OLED_ShowNum(1,9,ADValue,4);
        OLED_ShowNum(2,9,Voltage,1);//输出整数部分
        OLED_ShowNum(2,11,(uint16_t)(Voltage * 100) % 100,2);//输出小数部分
        
        Delay_ms(100);
    }
	
}

AD多通道

AD.c

#include "stm32f10x.h"                  // Device header

/**
  * @brief  初始化AD所需设备
  * @param  无
  * @retval 无
  */
void AD_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
    
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADCCLK为六分频
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
   
    //初始化ADC
    ADC_InitTypeDef ADC_InitStructure;
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC工作模式
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据对齐
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//外部触发转换选择

    //单通道单次转换非扫描模式    
    
    ADC_InitStructure.ADC_NbrOfChannel = 1;//通道数目
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;//扫描转换模式
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//非连续转换模式
    ADC_Init(ADC1,&ADC_InitStructure);
    
    ADC_Cmd(ADC1,ENABLE);//开启ADC1
    
    //进行ADC校准
    ADC_ResetCalibration(ADC1);//复位校准
    while(ADC_GetResetCalibrationStatus(ADC1) == SET);//等待复位校准完成
    ADC_StartCalibration(ADC1);//开始校准
    while(ADC_GetCalibrationStatus(ADC1) == SET);//等待校准完成
    
}

/**
*@brief  通过传入不同ADC通道,实现多通道AD,本质还是单通道
*@param  ADC_Channel:所选通道
*@retval 转化出的数据量最大为4095
  */
uint16_t AD_GetValue(uint8_t ADC_Channel)
{
     ADC_RegularChannelConfig(ADC1,ADC_Channel,1, ADC_SampleTime_55Cycles5);//配置输入通道
    //所选ADC设备,指定ADC通道,规则组序列器中的次序,指定通道采样时间(更快就选小参数,更稳定就选大参数)
   
    ADC_SoftwareStartConvCmd(ADC1,ENABLE);//开启软件触发转换
    while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//获取标志位状态(为Reset表示没有转换完成)
    //大约等待 (1 / 72MHz / 6) X (55.5 + 12.5) = 5.6us
    return ADC_GetConversionValue(ADC1);//调用后会自动清除EOC标志位
}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"

uint16_t AD0,AD1,AD2,AD3;

int main(void)
{
	OLED_Init();
	AD_Init();
	
    OLED_ShowString(1,1,"AD0:");
    OLED_ShowString(2,1,"AD1:");
    OLED_ShowString(3,1,"AD2:");
    OLED_ShowString(4,1,"AD3:");
    
	while(1)
	{
        AD0 = AD_GetValue(ADC_Channel_0);
        AD1 = AD_GetValue(ADC_Channel_1);
        AD2 = AD_GetValue(ADC_Channel_2);
        AD3 = AD_GetValue(ADC_Channel_3);
		
        OLED_ShowNum(1,5,AD0,4);
        OLED_ShowNum(2,5,AD1,4);
        OLED_ShowNum(3,5,AD2,4);
        OLED_ShowNum(4,5,AD3,4);
        
        Delay_ms(100);
    }
	
}

DMA

DMA转运数据

MyDMA.c

#include "stm32f10x.h"                  // Device header

uint16_t MyDMA_Size;

/**
  * @brief  初始化DMA
  * @param  无
  * @retval 无
  */
void MyDMA_Init(uint32_t AddrA,uint32_t AddrB,uint16_t Size)
{
    MyDMA_Size = Size;
    
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//开启MDA1时钟
    
    DMA_InitTypeDef DMA_InitStructrue;
    DMA_InitStructrue.DMA_PeripheralBaseAddr = AddrA;//外设起始地址
    DMA_InitStructrue.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据宽度
    DMA_InitStructrue.DMA_PeripheralInc = DMA_PeripheralInc_Enable;//外设是否自增
    DMA_InitStructrue.DMA_MemoryBaseAddr = AddrB;//存储器起始地址
    DMA_InitStructrue.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte ;//存储器数据宽度
    DMA_InitStructrue.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器是否自增
    DMA_InitStructrue.DMA_DIR = DMA_DIR_PeripheralSRC;//传输方向(外设作为源头)
    DMA_InitStructrue.DMA_BufferSize = Size;//传输计数器(传输次数)
    DMA_InitStructrue.DMA_Mode = DMA_Mode_Normal;//传输模式,是否使用自动重装(转运后停止)
    DMA_InitStructrue.DMA_M2M = DMA_M2M_Enable;//选择硬件触发,还是软件触发(软件触发)
    DMA_InitStructrue.DMA_Priority = DMA_Priority_Medium;//优先级(多个通道进行配置)
    DMA_Init(DMA1_Channel1,&DMA_InitStructrue);
    
    DMA_Cmd(DMA1_Channel1,DISABLE);//不让DMA初始化后立刻转运
}

/**
  * @brief  将外设数据通过DMA写入存储器
  * @param  无
  * @retval 无
  */
void MyDMA_Transfer(void)
{
    DMA_Cmd(DMA1_Channel1,DISABLE);//为传输计数器赋值,需先失能DMA
    DMA_SetCurrDataCounter(DMA1_Channel1,MyDMA_Size);//重新给传输计数器写入值
    DMA_Cmd(DMA1_Channel1,ENABLE);//使能DMA
    
    while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);//检查DMA1通道1转换完成的标志位(完成标志位置一)
    //未完成则一直空循环等待
    DMA_ClearFlag(DMA1_FLAG_TC1);//需要手动清除标志位
}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "MyDMA.h"

uint8_t DataA[] = {0x01,0x02,0x03,0x04};
uint8_t DataB[] = {0,0,0,0};

uint8_t i;

int main(void)
{
	OLED_Init();
    MyDMA_Init((uint32_t)DataA,(uint32_t)DataB,4);//DataA 转运至 Data
    
    OLED_ShowString(1,1,"DataA");
    OLED_ShowString(3,1,"DataA");
    OLED_ShowHexNum(1,8,(uint32_t)DataA,8);
    OLED_ShowHexNum(3,8,(uint32_t)DataB,8);
    
    for(i = 0;i < 4;i++)
    {
        OLED_ShowHexNum(2,3*i+1,DataA[i],2);
    }
    for(i = 0;i < 4;i++)
    {
        OLED_ShowHexNum(4,3*i+1,DataB[i],2);
    }
    
	while(1)
	{
       DataA[0] ++;
       DataA[1] ++;
       DataA[2] ++;
       DataA[3] ++;
        
        for(i = 0;i < 4;i++)
        {
            OLED_ShowHexNum(2,3*i+1,DataA[i],2);
        }
        for(i = 0;i < 4;i++)
        {
            OLED_ShowHexNum(4,3*i+1,DataB[i],2);
        }
       
       Delay_s(1);
        
       MyDMA_Transfer();//开始转运
        
         for(i = 0;i < 4;i++)
        {
            OLED_ShowHexNum(2,3*i+1,DataA[i],2);
        }
        for(i = 0;i < 4;i++)
        {
            OLED_ShowHexNum(4,3*i+1,DataB[i],2);
        }
        
       Delay_s(1);
	}
	
}

DMA+AD多通道

AD.c

#include "stm32f10x.h"                  // Device header

uint16_t AD_Value[4];

/**
  * @brief  初始化AD以及DMA
  * @param  无
  * @retval 无
  */
void AD_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//开启MDA1时钟
    
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADCCLK为六分频
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
     ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1, ADC_SampleTime_55Cycles5);//配置输入通道
     ADC_RegularChannelConfig(ADC1,ADC_Channel_1,2, ADC_SampleTime_55Cycles5);//配置输入通道
     ADC_RegularChannelConfig(ADC1,ADC_Channel_2,3, ADC_SampleTime_55Cycles5);//配置输入通道
     ADC_RegularChannelConfig(ADC1,ADC_Channel_3,4, ADC_SampleTime_55Cycles5);//配置输入通道
    //所选ADC设备,指定ADC通道,规则组序列器中的次序,指定通道采样时间(更快就选小参数,更稳定就选大参数)
   
    //初始化ADC
    ADC_InitTypeDef ADC_InitStructure;
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC工作模式
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据对齐
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//外部触发转换选择

    //ADC扫描模式+数据转运 
    //ADC连续扫描+DMA循环转运
    
    ADC_InitStructure.ADC_NbrOfChannel = 4;//通道数目
    ADC_InitStructure.ADC_ScanConvMode = ENABLE;//扫描转换模式(设置为扫描模式)
    //ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//是否为连续模式
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    ADC_Init(ADC1,&ADC_InitStructure);
    
    //配置DMA
    DMA_InitTypeDef DMA_InitStructrue;
    DMA_InitStructrue.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;//外设起始地址
    DMA_InitStructrue.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据宽度(16位)
    DMA_InitStructrue.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设是否自增(始终转运同一位置数据)
    DMA_InitStructrue.DMA_MemoryBaseAddr =  (uint32_t)AD_Value;//存储器起始地址
    DMA_InitStructrue.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//存储器数据宽度
    DMA_InitStructrue.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器是否自增
    DMA_InitStructrue.DMA_DIR = DMA_DIR_PeripheralSRC;//传输方向(外设作为源头)
    DMA_InitStructrue.DMA_BufferSize = 4;//传输计数器(传输次数)
    //DMA_InitStructrue.DMA_Mode = DMA_Mode_Normal;//传输模式,是否使用自动重装(转运后停止)
    DMA_InitStructrue.DMA_Mode = DMA_Mode_Circular;//循环模式
    DMA_InitStructrue.DMA_M2M = DMA_M2M_Disable;//选择硬件触发,还是软件触发(硬件触发)
    DMA_InitStructrue.DMA_Priority = DMA_Priority_Medium;//优先级(多个通道进行配置)
    DMA_Init(DMA1_Channel1,&DMA_InitStructrue);//这里的通道必须使用DMA1_Channel1,详情查表
    
    DMA_Cmd(DMA1_Channel1,ENABLE);//让DMA初始化后立刻转运
    
    ADC_DMACmd(ADC1,ENABLE);//开启ADC触发DMA信号
    
    ADC_Cmd(ADC1,ENABLE);//开启ADC1
    
    //进行ADC校准
    ADC_ResetCalibration(ADC1);//复位校准
    while(ADC_GetResetCalibrationStatus(ADC1) == SET);//等待复位校准完成
    ADC_StartCalibration(ADC1);//开始校准
    while(ADC_GetCalibrationStatus(ADC1) == SET);//等待校准完成
    
    ADC_SoftwareStartConvCmd(ADC1,ENABLE);//开启软件触发转换
}

/**
*@brief  通过传入不同ADC通道,实现多通道AD,本质还是单通道
*@param  ADC_Channel:所选通道
*@retval 转化出的数据量最大为4095
  */
//void AD_GetValue(void)
//{
//    DMA_Cmd(DMA1_Channel1,DISABLE);//为传输计数器赋值,需先失能DMA
//    DMA_SetCurrDataCounter(DMA1_Channel1,4);//重新给传输计数器写入值
//    DMA_Cmd(DMA1_Channel1,ENABLE);//使能DMA
//    
//    //ADC_SoftwareStartConvCmd(ADC1,ENABLE);//开启软件触发转换
//    
//    while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);//检查DMA1通道1转换完成的标志位(完成标志位置一)
//    //未完成则一直空循环等待
//    DMA_ClearFlag(DMA1_FLAG_TC1);//需要手动清除标志位
//}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"

int main(void)
{
	OLED_Init();
	AD_Init();
	
    OLED_ShowString(1,1,"AD0:");
    OLED_ShowString(2,1,"AD1:");
    OLED_ShowString(3,1,"AD2:");
    OLED_ShowString(4,1,"AD3:");
    
	while(1)
	{
        //AD_GetValue();
        
        OLED_ShowNum(1,5,AD_Value[0],4);
        OLED_ShowNum(2,5,AD_Value[1],4);
        OLED_ShowNum(3,5,AD_Value[2],4);
        OLED_ShowNum(4,5,AD_Value[3],4);
        
        Delay_ms(100);
    }
	
}

7


http://www.kler.cn/a/234789.html

相关文章:

  • 安卓从Excel文件导入数据到SQLite数据库的实现
  • 【机器学习】探索机器学习与人工智能:驱动未来创新的关键技术
  • 数学竞赛网站:构建互动学习的网络平台
  • 【IMU:视觉惯性SLAM系统】
  • 重拾设计模式--备忘录模式
  • ShardingSphere-Proxy 连接实战:从 Golang 原生 SQL 到 GORM 的应用
  • 【大厂AI课学习笔记】【1.6 人工智能基础知识】(3)神经网络
  • 锐捷(二十)DHCP Snooping + IP Source guard + ARP-check防ARP欺骗方案
  • 格子表单GRID-FORM | 文档网站搭建(VitePress)与部署(Github Pages)
  • SQL语句执行顺序相关问题
  • React Native开发iOS实战录
  • Android 自定义BaseFragment
  • Linux和Windows文件共享实现方式
  • 2024美赛C题保姆级分析完整思路代码数据教学
  • FL Studio版本升级-FL Studio怎么升级-FL Studio升级方案
  • 多进程服务器和多线程服务器
  • Vue - 快速入门(一)
  • 腾讯云4核8G12M轻量应用服务器性能够用吗?支持多少人?
  • sheng的学习笔记-部署-目录
  • 嵌入式电子产品开发感悟!
  • 深入学习Pandas:数据连接、合并、加入、添加、重构函数的全面指南【第72篇—python:数据连接】
  • C++局部变量与全局变量
  • ChatGPT高效提问—prompt实践
  • 修改SpringBoot中默认依赖版本
  • 快速手动完成 VS 编写脚本自动化:如何选取最高效的工作方式?
  • MySQL(基础)