STM32 HAL库学习系列第1篇 ADC配置 及 DAC配置

发布者:CelestialLight最新更新时间:2019-08-05 来源: eefocus关键字:STM32  HAL库  ADC配置  DAC配置 手机看文章 扫描二维码
随时随地手机看文章

ADC工作均为非阻塞状态

轮询模式


中断模式


DMA模式


库函数:


HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc);//轮询模式,需放在循环中不断开启

 

HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc);

 

HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout);//等待转换结束,只适用于轮询

 

HAL_StatusTypeDef HAL_ADC_PollForEvent(ADC_HandleTypeDef* hadc, uint32_t EventType, uint32_t Timeout);//

 

HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc);//中断模式

 

HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc);

 

void HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc);//中断

 

HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);//DMA模式

 

HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef* hadc);

 

uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc); //读取ADC的值

 

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc);//结束后回调

 

void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc);//转换过程中回调

 

void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc);

 

void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc);

 


校准模式:


校准ADC(HAL_ADCEx_Calibration_Start(&hadc);有些芯片不支持校准,F4不支持


----------------------------------------------------------------------------------------------------------------------------------


可变占空比设置


代码:


/*

实际使用时空置引脚状态下会飘动,大致为3.3V的一半,是芯片内部的原因

解决方式:引脚设置为下拉输入,F4没有这个设置

*/

 

/* USER CODE BEGIN 2 */

 

//  HAL_ADC_Start_IT(&hadc1);//开启ad转换

 

    HAL_TIM_Base_Start_IT(&htim3);//定时器中断

 

  HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);//开启输出pwm

 

  /* USER CODE END 2 */

 

  /* Infinite loop */

 

  /* USER CODE BEGIN WHILE */

 

  while (1)

 

  {

 

  /* USER CODE END WHILE */

 

  /* USER CODE BEGIN 3 */

 

        float pwmOut ;

 

        float dutyRatio;

 

        int lastTickMs=0;

 

        HAL_ADC_Start(&hadc1);

 

        

 

        if(HAL_GetTick() - lastTickMs >= 1000)

 

    {

 

        HAL_GPIO_TogglePin(RUNNING_LED_GPIO_Port,RUNNING_LED_Pin);

 

        lastTickMs = HAL_GetTick();      

 

    }

 

    HAL_Delay(1000);

 

        adcConvertedValue=HAL_ADC_GetValue(&hadc1);//获取AD转换值

 

    adcConvertedVoltage =(double)adcConvertedValue*3.3/4096;        

 

        

 

        pwmOut = adcConvertedValue*2400/4096;

 

        dutyRatio = pwmOut/2400 ;

 

        TIM3->CCR2 = pwmOut;    //(pwmOut)/ 2400    change Duty ratio

 

        

 

        printf("AD转换原始值 = %drn", adcConvertedValue);

 

        printf("计算得出电压值 = %f V rn",adcConvertedVoltage);

 

        printf("实际输出pwm值 = %frn", pwmOut);

 

        printf("占空比 = %f%%rn",dutyRatio*100);

 

  }

 

  /* USER CODE END 3 */

 

}

 


手动更改占空比


TIM3->CCR2   改变占空比


TIM3->ARR 改变频率


TIM3->PSC 


ADC_EXIT  触发引脚


32芯片自带的温度传感器,在16或者18通道


可以用来做对比

代码:


//对于12位的ADC,3.3V的ADC值为0xfff,温度为25度时对应的电压值为1.43V即0x6EE

#define V25  0x6EE

//斜率 每摄氏度4.3mV 对应每摄氏度0x05

#define AVG_SLOPE 0x05

  

 

/* 启动AD转换并使能DMA传输和中断 */

  HAL_ADC_Start_DMA(&hadcx,(uint32_t *)&ADC_ConvertedValue,sizeof(ADC_ConvertedValue)); 

 

  /* 无限循环 */

  while (1)

  {

    HAL_Delay(1000);

    Current_Temperature = (V25-ADC_ConvertedValue)/AVG_SLOPE+25;  //计算公式   

      /* 10进制显示 */

    printf("The IC current temperature = %d->%3d ℃n",ADC_ConvertedValue,Current_Temperature);

//    /* 16进制显示 */                        

//    printf("The current temperature= %04x n", Current_Temperature);  

  }

 


应用:测量压敏电阻阻值---还是测电压


  while (1)

  {

    HAL_Delay(1000);

    /* 3.3为AD转换的参考电压值,stm32的AD转换为12bit,2^12=4096,

       即当输入为3.3V时,AD转换结果为4096 */

    ADC_ConvertedValueLocal =(float)ADC_ConvertedValue*3.3/4096;

    flexiforce_R = 3.3*20/ADC_ConvertedValueLocal; // V(out) = Rref * Vcc / R;  Rref=20K  Vcc=3.3V

        printf("AD转换原始值 = 0x%04X rn", ADC_ConvertedValue);

        printf("计算得出电压值 = %f V rn",ADC_ConvertedValueLocal);

    printf("计算得出电阻值 = %f KRn",flexiforce_R);

  }

 

DMA多通道采集-----开启多通道设置,定义一个数组存放转换值


  while (1)

  {

    HAL_Delay(1000);

    /* 3.3为AD转换的参考电压值,stm32的AD转换为12bit,2^12=4096,

       即当输入为3.3V时,AD转换结果为4096 */   

    ADC_ConvertedValueLocal[0] =(float)(ADC_ConvertedValue[0]&0xFFF)*3.3/4096; // ADC_ConvertedValue[0]只取最低12有效数据

      ADC_ConvertedValueLocal[1] =(float)(ADC_ConvertedValue[1]&0xFFF)*3.3/4096; // ADC_ConvertedValue[1]只取最低12有效数据

    ADC_ConvertedValueLocal[2] =(float)(ADC_ConvertedValue[2]&0xFFF)*3.3/4096; // ADC_ConvertedValue[2]只取最低12有效数据

    ADC_ConvertedValueLocal[3] =(float)(ADC_ConvertedValue[3]&0xFFF)*3.3/4096; // ADC_ConvertedValue[3]只取最低12有效数据

   

    printf("CH1_PC0 value = %d -> %fVn",ADC_ConvertedValue[0]&0xFFF,ADC_ConvertedValueLocal[0]);

    printf("CH2_PC1 value = %d -> %fVn",ADC_ConvertedValue[1]&0xFFF,ADC_ConvertedValueLocal[1]);

    printf("CH3_PC2 value = %d -> %fVn",ADC_ConvertedValue[2]&0xFFF,ADC_ConvertedValueLocal[2]);

    printf("CH4_PC3 value = %d -> %fVn",ADC_ConvertedValue[3]&0xFFF,ADC_ConvertedValueLocal[3]);

 

    printf("已经完成AD转换次数:%dn",DMA_Transfer_Complete_Count);

    DMA_Transfer_Complete_Count=0;

    printf("n");  

  }

 

交叉模式---目的是两路ADC采集一路信号,可以获取双倍速度


/* 启动AD转换并使能DMA传输和中断 */

  HAL_ADC_Start(&hadcx2);

  HAL_ADCEx_MultiModeStart_DMA(&hadcx1,&ADC_ConvertedValue,sizeof(ADC_ConvertedValue)); //开启

 

  /* 无限循环 */

  while (1)

  {

    HAL_Delay(1000);

    /* 3.3为AD转换的参考电压值,stm32的AD转换为12bit,2^12=4096,

       即当输入为3.3V时,AD转换结果为4096 */

    ADC_ConvertedValueLocal[0] =(float)(ADC_ConvertedValue&0xFFF)*3.3/4096;  //ADC1

    ADC_ConvertedValueLocal[1] =(float)((ADC_ConvertedValue>>16)&0xFFF)*3.3/4096;   //ADC2

   

    printf("ADC1转换原始值 = 0x%04X --> 电压值 = %f V n", ADC_ConvertedValue&0xFFFF,ADC_ConvertedValueLocal[0]);   

    printf("ADC2转换原始值 = 0x%04X --> 电压值 = %f V n", (ADC_ConvertedValue>>16)&0xFFFF,ADC_ConvertedValueLocal[1]);     

    printf("已经完成AD转换次数:%dn",DMA_Transfer_Complete_Count);

    printf("rn");   

    DMA_Transfer_Complete_Count=0;

  }

 


DAC---数据转换

基本配置:


初始化


设置通道


启动DAC


在循环中改变dac_value值即可


库函数:


/* IO operation functions *****************************************************/

HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef* hdac, uint32_t Channel);

HAL_StatusTypeDef HAL_DAC_Stop(DAC_HandleTypeDef* hdac, uint32_t Channel);

HAL_StatusTypeDef HAL_DAC_Start_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t* pData, uint32_t Length, uint32_t Alignment); //需要函数中不断开启

HAL_StatusTypeDef HAL_DAC_Stop_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel);

HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data);

uint32_t HAL_DAC_GetValue(DAC_HandleTypeDef* hdac, uint32_t Channel);

  /* 初始化DAC */

  MX_DAC_Init();

  /* 设置DAC通道值 */

  HAL_DAC_SetValue(&hdac, DACx_CHANNEL, DAC_ALIGN_8B_R, dac_value);

  /* 启动DAC */

  HAL_DAC_Start(&hdac, DACx_CHANNEL);

 

  /* 无限循环 */

  while (1)

  {

    /* KEY1增加输出电压 */

    if(KEY1_StateRead()==KEY_DOWN)

    {

      if(dac_value<245)

        dac_value+=10;  

      else

        dac_value=255;       

      HAL_DAC_SetValue(&hdac, DACx_CHANNEL, DAC_ALIGN_8B_R, dac_value);  //设置值

    }

    /* KEY2减少输出电压 */

    if(KEY2_StateRead()==KEY_DOWN)

    {

      if(dac_value>10)

        dac_value-=10;  

      else

        dac_value=0;

      HAL_DAC_SetValue(&hdac, DACx_CHANNEL, DAC_ALIGN_8B_R, dac_value);

    }

  }

输出正弦波----DMA模式


就是预设一组值,不断改变


const uint16_t CH_value[32] = {

    2448,2832,3186,3496,3751,3940,4057,4095,4057,3940,

    3751,3496,3186,2832,2448,2048,1648,1264,910,600,345,

    156,39,0,39,156,345,600,910,1264,1648,2048

};

 

 

 

 

int main(void)

{  

  /* 复位所有外设,初始化Flash接口和系统滴答定时器 */

  HAL_Init();

  /* 配置系统时钟 */

  SystemClock_Config();

 

 

  /* 初始化DAC */

  MX_DAC_Init();

  /* 启动定时器 */

  HAL_TIM_Base_Start(&htim6);

  /* 启动DAC DMA功能 */

  HAL_DAC_Start_DMA(&hdac,DACx_CHANNEL,(uint32_t *)CH_value,32,DAC_ALIGN_12B_R);

  /* 无限循环 */

  while (1)

  {

   

  }

}


关键字:STM32  HAL库  ADC配置  DAC配置 引用地址:STM32 HAL库学习系列第1篇 ADC配置 及 DAC配置

上一篇:STM32 HAL库学习系列第3篇 常使用的几种延时方式
下一篇:STM32 Hal库SPI中断

推荐阅读最新更新时间:2024-11-10 18:40

详解STM32单片机堆栈
学习STM32单片机的时候,总是能遇到“堆栈”这个概念。分享本文,希望对你理解堆栈有帮助。 对于了解一点汇编编程的人,就可以知道,堆栈是内存中一段连续的存储区域,用来保存一些临时数据。堆栈操作由PUSH、POP两条指令来完成。而程序内存可以分为几个区: 栈区(stack) 堆区(Heap) 全局区(static) 文字常亮区程序代码区 程序编译之后,全局变量,静态变量已经分配好内存空间,在函数运行时,程序需要为局部变量分配栈空间,当中断来时,也需要将函数指针入栈,保护现场,以便于中断处理完之后再回到之前执行的函数。 栈是从高到低分配,堆是从低到高分配。 普通单片机与STM32单片机中堆栈的区别 普通单片机启动时,不需要用b
[单片机]
详解<font color='red'>STM32</font>单片机堆栈
普通8位单片机和STM32单片机复位电路区别
普通8位单片机,如AT、STC等芯片厂商,单片机须使用高电平复位,复位后保持低电平 STM32单片机,使用低电平进行复位,NRST复位引脚在一般情况需保持高电平电路才能正常工作。 另外单片机上电时间是有要求的,所以因根据数据手册匹配指定的RC复位电路。
[单片机]
STM32单片机SPI总线与FPGA的通信设计
最近在研究SPI总线,至于协议和硬件描述就不多说了 四线包括时钟、片选、接收、发送 初始化SP SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主模式 SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; //16bit宽度 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2E
[单片机]
STM32 外部(IO)中断EXTI的应用
a) 目的:跟串口输入类似,不使用中断进行的IO输入效率也很低,而且可以通过EXTI插入按钮事件,本节联系EXTI中断。 b) 初始化函数定义: void EXTI_Configuration(void); //定义IO中断初始化函数 c) 初始化函数调用: EXTI_Configuration();//IO中断初始化函数调用简单应用: d) 初始化函数: void EXTI_Configuration(void) { EXTI_InitTypeDef EXTI_InitStructure; //EXTI初始化结构定义 EXTI_Cle
[单片机]
stm32 HAL 库 串口开关 串口接收开关
适用于HAL库 1、串口接收打开或关闭 #define UART_ENABLE_RE(USARTx) USARTx.Instance- CR1|= (uint32_t)0x0004 #define UART_DISABLE_RE(USARTx) USARTx.Instance- CR1&= (~(uint32_t)0x0004) 如使能串口1的接收:UART_ENABLE_RE(huart1); 2、串口打开或者关闭 #define UARTx_ENABLE(USARTx) (USARTx.Instance)- CR1 |= USART_CR1_UE #define UARTx_DI
[单片机]
stm32的中断与事件
事件:是表示检测有一某件触发事件发生了。 中断:有某个事件发生并产生中断,并跳转到对应的中断处理程序中。 事件可以触发中断,也可以不触发 中断有可能被更优先的中断屏蔽,事件不会 事件本质上就是一个触发信号,是用来触发特定的外设模块或核心本身(唤醒). 事件只是一个触发信号(脉冲),而中断则是一个固定的电平信号
[单片机]
STM32菜鸟成长记录---GPIO的使用
span style= font-size:14px; /span span style= font-size:14px; #include stm32f10x_lib.h #include stm32f10x.h GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO宏操作结构体 void Delay(__IO uint32_t nCount)//__IO的宏定义volatile { for(; nCount != 0; nCount--); } /*初始化嵌入式Flash接口,初始化PLL使其达到系统可用频率*/ vo
[单片机]
<font color='red'>STM32</font>菜鸟成长记录---GPIO的使用
OpenMV数据打包发送以及STM32对数据的解析(串口方式)
今天尝试了使用Openmv用串口发送数据,32接收,遇到了一些坑,但是最后还是实现了,难住我的地方并不是关于传输的代码,而是那个板子串口3不知道因为什么原因接收到的数据是错误的,这个原因正在寻找,找到了再记录。 Python提供了便捷的将数据打包的方法。我使用的方法就是将数据以二进制的方式打包然后通过串口逐字节发送。 struct模块的pack(fmt, v1, v2, ...) 函数提供了按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流)的功能,关与格式,有一个表定义了所有支持的字符及数据格式,如下: microPython的串口使用方法也是很简单的,代码如下: uart = py
[单片机]
OpenMV数据打包发送以及<font color='red'>STM32</font>对数据的解析(串口方式)
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved