STM32CubeMX+Keil+Proteus仿真ADC采集

本文说明

项目所要实现的功能

  1. 采用轮询模式每隔0.5秒进行ADC采集
  2. 格式化输出采样值和电压值
  3. 在ADC转换过程中点亮LED灯

模数转换器(ADC)概述

ADC:Analog-to-Digital Converter
将时间和幅值连续的模拟量转化为时间和幅值离散的数字量
A/D转换一般要经过采样、保持、量化和编码4个过程

ADC性能指标

量程:指ADC所能输入模拟信号的类型和电压范围,即参考电压。信号类型包括单极性和双极性。
转换位数:量化过程中的量化位数n。 A/D转换后的输出结果用n位二进制数来表示。
【例】:10位ADC的输出值就是0~1023。
分辨率:ADC能够分辨的模拟信号最小变化量。计算公式是,分辨率 = 量程 / 2的n次方
【例】:量程为单极性0-5V,8位ADC的分辨率是,5 / 256 = 0.0195V
转换时间:ADC完成一次完整的A/D转换所需要的时间,包括采样、保持、量化、编码的全过程。

ADC数据采样的计算应用

有一个温度测控系统,已知温度传感器在0到100度之间为线性输出,参考电压为5V,采用8为的A/D转换器,0度的时候,测的电压为1.8伏,100度的时候,测的电压为4.3伏。
【问题1】:系统的分辨率是多少?
【问题2】:采集到数据10010001,表示多大电压?温度是多少?

由于温度是线性变化,先求得斜率k,得到温度和电压的关系表达式。
k = (100 – 0)/(4.3-1.8) = 40, y = 40*(x-1.8) (x为采样得到的电压)
由于采用的是8为ADC,参考电压为5V,所以分辨率为:
5 / 256 = 0.0195V = 19.5mV(最小能分辨的电压,分辨率)
0.0195 * 40 = 0.78度(最小能分辨的温度)
因为 10010001B = 91H = 145, 所以 0.0195 * 145 = 2.8275V
该电压信号对应的温度是:(2.83V – 1.8V) * 40 = 41.1摄氏度

HAL库中关于ADC的重要函数

共分为三种:轮询中断DMA三种模式
开启ADC函数

HAL_ADC_Start(&hadc1);     //轮询模式开启ADC
HAL_ADC_Start_IT(&hadc1); //中断模式开启ADC
HAL_ADC_Start_DMA(&hadc1);//DMA模式开启ADC

关闭ADC函数

HAL_ADC_Stop(&hadc1);    //轮询模式关闭ADC
HAL_ADC_Stop_IT(&hadc1); //中断模式关闭ADC
HAL_ADC_Stop_DMA(&hadc1);//DMA模式关闭ADC

读取ADC转换值

HAL_ADC_GetValue(&hadc1);

ADC校准函数(通常在ADC初始化之后加上该函数)

MX_ADC1_Init();                     //ADC初始化
HAL_ADCEx_Calibration_Start(&hadc1);//AD校准 

等待转换结束函数(用于轮询模式)

void HAL_ADC_PollForConversion(&hadc1, 50){//第二个参数为等待时间
//判断转化函数是否结束的条件语句
if(HAL_ADC_PollForConversion(&hadc1,10) == HAL_OK){
	/*User Code*/
}
}

ADC中断回调函数(用于中断模式,中断发生则进入该函数)

void HAL_ADC_ConvCpltCallback(&hadc1){
if(hadc->Instance == ADC1){
	/*User Code*/
}
}

STM32CubeMX配置ADC

时钟配置
在RCC中选择HSE,配置时钟树
需要注意的是为确保转化精确度,ADC的时钟不能超过14MHz
如图是ADC Prescaler(ADC预分频器,ADC模块的时钟来源)是12MHz
当然你配置的一旦超过14MHz,STM32CubeMX会报错

在这里插入图片描述
ADC配置
如图进行配置,ADC选择通道1,自动配置PA1,其他Setting用默认的即可

在这里插入图片描述
简单介绍一下有用的参数
Mode——Independent mode
即独立模式,每个ADC独立工作,好像就看到这一个选项。。。
Data Alignment (数据对齐方式)
一般选择右对齐,除非有特殊要求
Scan Conversion Mode( 扫描模式 )
用到多个通道会自动设置为ENABLE
Number OF Conversion(转换通道数)
用到几个通道就选几,默认自然是1
Continuous Conversion Mode(连续转换模式)
连续不连续的区别在于多个数据转化是全部转换完成再停止,还是转换一个停一下,等待下一个触发转化命令
Rank——Sampling Time(采用周期),默认1.5个周期,不知道干嘛用

其他常规配置就不再赘述,可以看我之前的博客
生成代码即可

Keil代码编辑

由于只需要输出,不需要输入,所以就不用串口收发函数了
这里用printf()函数输出数据信息

/* printf重定向 */
int fputc(int ch ,FILE *f){
	uint8_t temp[1] = {ch};
	HAL_UART_Transmit(&huart1, temp, 1, 2);
	return ch;
}

由于经常使用,这里我们把它写入Keil的Template下,以便随时调用

在这里插入图片描述
新建一个模板,名为"printf",然后编辑代码,如图所示

在这里插入图片描述
还有一点需要注意的,使用fput和fgetc函数达到重定向C语言HAL库输入输出函数必须在MDK的工程选项把“Use MicroLIB”勾选上,如图所示
MicoroLIB是缺省C库的备选库,它对标准C库进行了高度优化使代码更少,占用更少资源。

在这里插入图片描述

自定义转换函数

void ADC_TO_VOL()
{
	HAL_ADC_Start(&hadc1);
	LED_ON;
	if(HAL_ADC_PollForConversion(&hadc1,10) == HAL_OK)
	{
		ADC_Value = HAL_ADC_GetValue(&hadc1);		
	}
	printf("ADC 采样值: %d, 电压值: %.4fV \r\n",ADC_Value,ADC_Value*3.3f/4096);	
	LED_OFF;
}

注意用printf()函数时,要引入stdio.h文件

#include "stdio.h" 

然后我们在main函数while循环里写入代码即可,如下所示

  while (1)
  {
	  ADC_TO_VOL();
	  HAL_Delay(500);		
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

写完了,编译运行生成hex文件即可

Proteus仿真

原理图如下

在这里插入图片描述
注意虚拟终端的连线方式,由于只要输出即可,所以我们只要将TX(PA9端口)连RXD

滑动变阻器如何找到?
在元件库里搜索"POT-HG"即可找到带数显的滑动变阻器,普通款就是"POT"

仿真结果

程序没问题
采样结果一直是0,不知道是为什么

在这里插入图片描述
但是把ADC线直接接电源上却能正常显示

在这里插入图片描述
就很奇怪,希望有人能解答一下,先感谢一下了,困扰好多天了

总结

  1. 学习了ADC的相关概念
  2. 学习与ADC相关的重要函数
  3. 轮询方式和中断方式其实就是阻塞式和非阻塞式,一个等待处理结束再写用户命令,另一个在中断回调函数写用户命令
  4. 本文展示了轮询方式,中断方法就不写了,挺简单的,有空再补
  5. 用具体的项目实现ADC采集,采集的电压其实也不精准

我是爱学习的诸葛铁锤,觉得有用的话点个赞哈,啾咪

<think>嗯,用户的问题是关于如何在STM32上配置或仿真PCF8751芯片的教程或方案,特别是使用STM32CubeMXProteus。首先,我需要确认PCF8751的型号是否正确,因为根据提供的引用,用户可能指的是PCF8574、PCF8575、PCF8591或PCF8563,但PCF8751这个型号在引用中没有提到。这可能是一个拼写错误或者用户记错了型号。因此,首先需要建议用户确认型号,并假设可能的正确型号,如PCF8574或PCF8575。 接下来,假设用户确实是指PCF8574或类似的I2C扩展芯片,我需要从引用中找到相关的配置信息。引用[1]提到PCF8574是8路I/O扩展,引用[4]提到PCF8575是16路,两者都是I2C接口。所以,基于这些信息,可以推断出配置步骤可能类似。 用户需要使用STM32CubeMX进行配置,然后进行Proteus仿真。首先,在STM32CubeMX中配置I2C外设,设置正确的引脚,比如I2C1的SCL和SDA,并生成代码。然后,在代码中使用HAL库函数进行I2C通信,比如发送数据到PCF8574的地址,或者读取输入状态。 在Proteus中,需要添加PCF8574元件,连接I2C线路,并配置正确的从机地址。根据引用[1],可能需要设置A0、A1、A2地址引脚来确定I2C地址。例如,如果地址引脚都接地,地址可能是0x20。 另外,用户可能需要了解如何编写代码,包括初始化I2C、发送和接收数据。需要注意HAL库的函数调用,比如HAL_I2C_Master_Transmit和HAL_I2C_Master_Receive,以及处理可能的错误。 同时,仿真时可能需要使用虚拟终端或逻辑分析仪来监控I2C通信,确保数据正确传输。引用中的示例使用了FreeRTOS,所以如果用户的项目涉及实时操作系统,也需要在CubeMX中配置FreeRTOS,并确保任务调度正确。 最后,需要提醒用户注意硬件连接的正确性,比如上拉电阻是否添加,I2C总线的速度设置是否匹配,以及地址是否正确。如果用户遇到问题,建议检查这些方面,并参考提供的引用资源中的详细步骤。</think>### STM32CubeMXProteus中PCF8751配置及仿真方法 #### 问题分析 根据引用内容,PCF8751可能是输入/输出扩展芯片的笔误,实际可能是以下I²C接口芯片之一: - **PCF8574**(8位I/O扩展,引用[1][^1]) - **PCF8575**(16位I/O扩展,引用[4][^4]) - **PCF8591**(8位ADC/DAC,引用[2][^2]) 以下以**PCF8574(8位I/O扩展)**为例说明配置流程。 --- ### 一、STM32CubeMX配置步骤 1. **创建工程** - 选择STM32F103C8T6芯片,启用外部高速时钟(HSE) - 配置RCC为Crystal/Ceramic Resonator 2. **I2C外设配置** - 启用I2C1模式为**I2C** - 配置SCL/SDA引脚(如PB6/PB7) - 参数设置: ```c Timing: Standard Mode (100 kHz) Own Address: 0x00 (主机模式无需地址) ``` 3. **FreeRTOS集成(可选)** - 在Middleware中启用FREERTOS - 创建I2C读写任务(建议优先级为`osPriorityNormal`) 4. **生成代码** - Toolchain选择MDK-ARM或SW4STM32 - 勾选生成外设初始化代码 --- ### 二、代码开发(Keil/STM32IDE) ```c // 定义PCF8574地址(A0-A2接地时地址为0x20) #define PCF8574_ADDR 0x20 << 1 // I2C地址需左移1位 // 发送8位数据到PCF8574 HAL_I2C_Master_Transmit(&hi2c1, PCF8574_ADDR, &data, 1, HAL_MAX_DELAY); // 从PCF8574读取输入状态 uint8_t input_data; HAL_I2C_Master_Receive(&hi2c1, PCF8574_ADDR, &input_data, 1, HAL_MAX_DELAY); ``` --- ### 三、Proteus仿真设置 1. **元件添加** - 搜索添加`STM32F103C8`、`PCF8574`、`I2C DEBUGGER` - 连接电路: ``` STM32 PB6 -> PCF8574 SCL STM32 PB7 -> PCF8574 SDA PCF8574 A0-A2接地(地址0x20) ``` 2. **固件加载** - 右键STM32芯片,加载生成的`.hex`文件 - 设置晶振频率为8MHz(与CubeMX配置一致) 3. **调试监控** - 添加I2C Debugger监控总线数据 - 使用虚拟终端观察调试输出(需代码中启用UART) --- ### 四、关键注意事项 1. **地址冲突**:若总线上有多个I²C设备,需通过A0-A2引脚设置不同地址[^4] 2. **上拉电阻**:SCL/SDA线需接4.7kΩ上拉电阻(Proteus中可省略,实物必须添加) 3. **时序匹配**:CubeMX中I2C时序配置需与Proteus模型参数一致 4. **电平兼容**:PCF8574工作电压范围2.5-6V,需与STM32电平匹配[^4] ---
评论 68
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值