打印
[应用相关]

STM32F4+薄膜压力传感器(FSR)AO模拟输出程序&ADC模数转换器详解

[复制链接]
143|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-3-27 08:19 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

STM32F4+薄膜压力传感器(FSR)AO模拟输出程序:

main.c

main.c是用于读取薄膜压力传感器(FSR)的模拟输出,并将其映射到实际压力值范围内。主要功能是读取薄膜压力传感器的模拟输出,并将其转换为相应的压力值。

首先包含了一些必要的头文件,包括STM32的相关头文件以及自定义的延迟、串口、ADC和FSR的头文件。

定义了一些常量,如最小和最大量程、最小和最大电压范围等。

在main()函数中,初始化延迟、中断和串口,并进行ADC的初始化。

进入主循环后,通过Get_Adc_Average()函数获取ADC的10次平均值,并将其映射到电压值范围内。然后根据电压值的情况,计算相应的压力值。

使用printf()函数输出ADC值、电压值和压力值。

最后通过延迟一段时间,实现数据的周期性读取。

#include "stm32f4xx.h"                  // Device header
#include <stdint.h>
#include <stdbool.h>  
#include "Delay.h"
#include "LED.h"
#include "Key.h"
#include "OLED.h"
#include "usart1.h"
#include "adc.h"


//最小量程
#define PRESS_MIN        20
//最大量程
#define PRESS_MAX        6000
#define VOLTAGE_MIN 100
#define VOLTAGE_MAX 3300
u8 state = 0;
u16 val = 0;
u16 value_AD = 0;

long PRESS_AO = 0;
int VOLTAGE_AO = 0;

long map(long x, long in_min, long in_max, long out_min, long out_max);



int main(void)
{
       
        I2C_Configuration();//配置CPU的硬件I2C       
        OLED_Init();
        Adc_Init();
       
       
        OLED_CLS();//清屏

       
        while(1)
        {
               
                value_AD = Get_Adc_Average(13,10);        //10次平均值
                VOLTAGE_AO = map(value_AD, 0, 4095, 0, 3300);
                if(VOLTAGE_AO < VOLTAGE_MIN)
                {
                        PRESS_AO = 0;
                }
                else if(VOLTAGE_AO > VOLTAGE_MAX)
                {
                        PRESS_AO = PRESS_MAX;
                }
                else
                {
                        PRESS_AO = map(VOLTAGE_AO, VOLTAGE_MIN, VOLTAGE_MAX, PRESS_MIN, PRESS_MAX);
                }
                //printf("AD值 = %d,电压 = %d mv,压力 = %ld g\r\n",value_AD,VOLTAGE_AO,PRESS_AO);
                OLED_ShowNum(1,1,value_AD,5);
                OLED_ShowNum(2,1,VOLTAGE_AO,5);
                OLED_ShowNum(3,1,PRESS_AO,5);
                Delay_ms(500);
        }       
}
long map(long x, long in_min, long in_max, long out_min, long out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;}

adc.c

博主使用的adc通道是PC3-ADC123_IN13(adc1和adc2和adc3的通道13)

首先Adc_Init初始化adc

定义了需要用到的结构体:GPIO_InitTypeDef、ADC_InitTypeDef和ADC_CommonInitTypeDef。
使能了ADC1通道的时钟和GPIOC端口的时钟。
配置PC3引脚作为模拟通道输入引脚,设置为模拟输入引脚并且不使用上拉或下拉。
对ADC1进行复位操作。
初始化ADC Common 结构体参数,包括禁止DMA直接访问模式、独立ADC模式、时钟分频等。
初始化ADC Init 结构体参数,包括单通道模式、数据右对齐、外部触发通道、ADC分辨率等。
根据ADC_Init结构体中的参数初始化ADC1外设寄存器。
使能ADC1。
然后是获取ADC转换结果的函数。函数名称为Get_Adc(u8 ch)

使用ADC_RegularChannelConfig函数设置ADC规则组通道和采样时间。
使用ADC_SoftwareStartConv函数启动ADC转换。
使用while循环等待ADC转换结束,通过检查ADC_FLAG_EOC标志位来判断转换是否完成。
使用ADC_GetConversionValue函数获取最近一次ADC转换的结果,并将其返回。
最后是获取指定通道(ch参数)的ADC转换结果,并对转换结果进行多次采样(times次),然后计算这些采样值的平均值。

使用for循环对指定通道进行多次采样,每次采样后将转换值累加到temp_val变量中。
在每次采样之间通过Delay_ms函数添加延时,这有助于确保每次转换之间有足够的间隔。
最后,将temp_val除以采样次数times,得到平均值,并将其返回。
#include "adc.h"
#include "Delay.h"
          
/*
Ao:接ADC模拟电压信号输出--PC3-ADC123_IN13(adc1和adc2和adc3的通道13)
*/          


//初始化ADC
//规则通道                                                                                                                                  
void  Adc_Init(void)
{        
        //定义结构体
        GPIO_InitTypeDef GPIO_InitStructure;
        ADC_InitTypeDef ADC_InitStructure;
        ADC_CommonInitTypeDef ADC_CommonInitStructure;
       
        //使能ADC1通道时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE );          
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
       
       
        //PC3 作为模拟通道输入引脚 不上拉不下拉                        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                //模拟输入引脚
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;        //不上拉不下拉
        GPIO_Init(GPIOC, &GPIO_InitStructure);       
       
       
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE);   //ADC1复位
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE);    //复位结束
       
        //ADC Common 结构体 参数 初始化
        ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; // 禁止DMA直接访问模式       
        ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;// 独立ADC模式
        ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;// 时钟为fpclk x分频       
        ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;// 采样时间间隔       
        ADC_CommonInit(&ADC_CommonInitStructure);
       
        //ADC Init 结构体 参数 初始化
        ADC_StructInit(&ADC_InitStructure);
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//模数转换工作在单通道模式
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//ADC数据右对齐
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;//外部触发通道,本例子使用软件触发,此值随便赋值即可
        ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止外部边沿触发
        ADC_InitStructure.ADC_NbrOfConversion = 1;//顺序进行规则转换的ADC通道的数目
        ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;// ADC 分辨率
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;//模数转换工作在单次转换模式
        ADC_Init(ADC1, &ADC_InitStructure);        //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   

        ADC_Cmd(ADC1, ENABLE);        //使能指定的ADC1

}                                  
//获得ADC值
//返回值:转换结果
u16 Get_Adc(u8 ch)   
{
                    
        ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_56Cycles);//设置ADC规则组通道,一个序列,采样时间480
        ADC_SoftwareStartConv(ADC1);//使能指定的ADC1的软件转换启动功能
        while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//读取状态寄存器的状态位EOC,等待转换结束
        return ADC_GetConversionValue(ADC1);//返回最近一次的ADC1规则组的转换结果
       
}

//获取通道ch的转换值,取times次,然后平均
//ch:通道编号  times:获取次数
//返回值:通道ch的times次转换结果平均值
u16 Get_Adc_Average(u8 ch,u8 times)
{
        u32 temp_val=0;
        u8 t;
        for(t=0;t<times;t++)
        {
                temp_val+=Get_Adc(ch);//取times次通道值进行求和
                Delay_ms(5);
        }
        return temp_val/times; //返回平均值
}          


adc.h

#ifndef __ADC_H
#define __ADC_H       

#include "stm32f4xx.h"                  // Device header

typedef uint16_t u16;
typedef uint8_t u8;

void Adc_Init(void);
u16  Get_Adc(u8 ch);
u16 Get_Adc_Average(u8 ch,u8 times);

#endif
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/m0_61712829/article/details/136820252

使用特权

评论回复
沙发
盗铃何须掩耳| | 2024-3-27 13:16 | 只看该作者
就是通过读取AD值转换为压力

使用特权

评论回复
板凳
Undshing| | 2024-3-27 15:18 | 只看该作者
触摸也是这样实现的吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1360

主题

13980

帖子

8

粉丝