【蓝桥杯嵌入式】ADC数据传输与EEPROM实现数据的读写

ADC的单通道数据传输(常用)

ADC
ADC的转化方式:

  • 单次转化,一次只转化一个通道
  • 连续转化,转换完成一个通道 后 立即自动执行下一个通道的转换
  • 扫描模式,开启一次后,自动的连续读取多个通道

ADC的三种工作方式

  • 阻塞模式(查询模式)
  • 中断模式
  • DMA模式

单通道/多通道

单通道: 扫描模式关闭

  • 配置为“单次转换模式”,ADC通道转换一次后,就停止转换。等待再次使能后才会重新转化 。
  • 配置为“连续转换模式”,ADC通道转换一次后,接着进行下一次转换,不斯连续。

**多通道:**扫描模式使能

  • 配置为“单次转换模式”,ADC的多个通道,按照配置的顺序依次转换一次后,就停止转换。等到再次使能后才会重新转换
  • 配置为“连续转换楔式”,ADC的多个通遊,按照配置的顺序依次转换一次后,接着进行下一次转换,不断连续。

cubemx配置

通过查看原理可得,开发板自带2路可调电阻用于ADC检测端口电压值,分别通过跳线帽接到单片机的PB15与PB12接口

cubemx引脚配置
因此将单片机的PB15引脚配置为ADC2_IN15,将PB12引脚配置ADC1_IN11,2路ADC用于采集引脚电压值。

启动ADC的单通道数据采集

程序设计

main.c初始化中,启动ADC自校准, 保证数据的准确性,否则会有偏差

HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);
HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED);

ADC获取模拟电压功能函数

double getAdcVal(ADC_HandleTypeDef *pin)
{
	double dat;
	HAL_ADC_Start(pin);							//启动ADC
	dat = HAL_ADC_GetValue(pin);		//获取ADC数值
	return dat * 3.3 / 4096;				//对ADC数据进行转化
}	

ADC进程函数,记得需要把adc_process()函数放到main.c的while(1)中执行!!!

u32 adc_tick = 0;
void adc_process(void)
{
	//每200ms读取一次ADC数据
	if(uwTick - adc_tick < 200)
		return;
	adc_tick = uwTick;
	
	vr37 = getAdcVal(&hadc2);
	vr38 = getAdcVal(&hadc1);
}

将采集到的ADC数据放到LCD显示进程函数中进行显示

void lcd_process(void)
{
	if(ui == 0)
	{
		sprintf(text,"     vr37:%.2fV    ",vr37);
		LCD_DisplayStringLine(Line3, (unsigned char *)text);
		sprintf(text,"     vr38:%.2fV    ",vr38);
		LCD_DisplayStringLine(Line5, (unsigned char *)text);
	}
}

I2C协议与EEPROM实现数据的读写

  通过查看原理图,开发板自带一个24C02的EEPROM芯片,用于数据的掉电保存,该芯片通过I2C总线的形式连接到单片机的PB6和PB7引脚

cubemx配置(可不配 / 通过程序设置)

将官方给的i2c_hal.c源文件添加至工程,并初始化通过程序初始化I2C(相当于cubemx的配置工作)

I2CInit();

EEPROM实现u8数据的读写(常用)

在 i2c_hal.c文件中定义数据的存储与读取函数如下所示:

eeprom的数据读取函数

uchar eeprom_read(uchar addr)
{
	uchar dat;
	I2CStart();			//启动I2C
	I2CSendByte(0xa0);	//连接芯片
	I2CWaitAck();		//等待应答
	I2CSendByte(addr);	//发送要读取的地址
	I2CWaitAck();		//等待应答
	I2CStop();			//停止I2C
	
	I2CStart();			//重新打开I2C
	I2CSendByte(0xa1);	//启动读取数据
	I2CWaitAck();		//等待应答
	dat = I2CReceiveByte();	//接收数据
	I2CWaitAck();			//等待应答
	I2CStop();				//停止I2C
	return dat;				//发送数据
}

eeprom的数据存储函数

void eeprom_write(uchar addr, uchar dat)
{
	I2CStart();			//启动I2C
	I2CSendByte(0xa0);	//连接芯片
	I2CWaitAck();		//等待应答
	I2CSendByte(addr);	//发送存储地址
	I2CWaitAck();		//等待应答
	I2CSendByte(dat);	//发送存储的数据
	I2CWaitAck();		//等待应答
	I2CStop();			//停止
	HAL_Delay(5);		//延时等待
}

其他类似数据的读写

u16/u32类型数据的读写: 将u16类型的数据的高8位与低8位分别进行读写操作即可

void eeprom_write_uint(uchar addr, uint dat)
{
	eeprom_write(addr,dat & 0xff);			//存储低八位
	eeprom_write(addr+1,(dat>>8) & 0xff);	//存储高八位
}

uint eeprom_read_uint(uchar addr)
{
	//获取高8位 + 低8位 并返回
	uint dat = (eeprom_read(addr+1) << 8) +  eeprom_read(addr);
	return dat;
}

浮点类型数据的读写: 首先将浮点类型的数据*100,转化为16位的数据,再进行数据存储,在读取返回时获取16位的数据,并除以100即得到浮点类型的目标数据。

void eeprom_write_double(uchar addr, double dat_double)
{
	uint dat = (uint)(dat_double * 100);	//现将浮点数转化为uint类型
	eeprom_write(addr,dat & 0xff);	
	eeprom_write(addr+1,(dat>>8) & 0xff);
	
}
double eeprom_read_double(uchar addr)
{
	uint dat = (eeprom_read(addr+1) << 8) +  eeprom_read(addr);\
	return dat / 100.0;
}

开发板的首次上电与默认参数设置

void set_up(void)
{
	//首次上电 地址中数据为空(255)
	if(eeprom_read(123) != 123)
	{
		eeprom_write(123,123);		//特定地址写入数据
		eeprom_write(1,60);			//设置默认参数
		eeprom_write_double(2,1.50);
		eeprom_write_double(4,1.50);
		pwm = eeprom_read(1);
	}
	//开发板非第一次上电 直接读取eeprom中的数据
	else
	{
		pwm = eeprom_read(1);
	}
}

数字电位器与ADC多通道的DMA传输

MCP4017数字电位器

  通过查看开发板原理图,I2C总线上还挂载了一个MCP4017芯片,其中MCP4017是一个128步进,100KΩ的数字电位器,该电路是一个电阻分压结构,与一个10KΩ的R17串联,电压输出连接到开发板的PB14引脚,通过设置MCP4017的步进来改变电阻,最后可读取PB14的电压值,其中PB14的电压计算公式为:V=RWB/(RWB+ 10)* 3.3;

其中MCP4017硬件电路原理图如下所示:

MCP数字电位器更改阻值函数:

  • 数字电位器的地址为0x5e
  • 数字电位器实际的阻值 RWB = (dat / 127) * 100 KΩ
void mcp_write(uchar dat)
{
	I2CStart();			//启动I2C
	I2CSendByte(0x5e);	//写入地址
	I2CWaitAck();		//等待应答
	I2CSendByte(dat);	//写入步进长度
	I2CWaitAck();		//等待应答
	I2CStop();			//停止
	HAL_Delay(5);
}

ADC多通道的DMA传输

DMA

  • DMA是内存到内存或内存到存储的直接映射,数据不用经过CPU而直接由硬件进行数据的传递

  • 可以直接将读取的ADC值放到内存变量中。

  • STM32系列的大多数产品ADC属于SAR型 (逐次逼近型),每次转换需要一定的时间,尤其是多通道转换的场合。

cubemx配置

通过同时采集PB14引脚及其PB12引脚的R38的电压值,通过ADC1的多个通道转化,并通过DMA数据传输。

首先对cubemx进行引脚配置,并设置ADC1通道5和通道11为单端模式,并为ADC1添加DMA,模式为轮询模式

其次对ADC进行参数设置,设置转化通道数,使能连续转换、使能DMA连续请求,并设置各个通道的采样时间

程序设计

uchar adc_buf[2];			//存放adc数据buf

mcp_write(63);				//设置mcp电位器电阻 50KΩ
HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);	//ADC1自校准
HAL_ADC_Start_DMA(&hadc1,(uint *)adc_buf,2);			//启动ADC1的DMA传输

adc数据显示

sprintf(text,"    adc1:%.2f",adc_buf[0]*3.3/4096);
LCD_DisplayStringLine(Line8, (unsigned char *)text);	//LCD显示函数
sprintf(text,"    adc2:%.2f",adc_buf[1]*3.3/4096);
LCD_DisplayStringLine(Line9, (unsigned char *)text);	//LCD显示函数
  • 9
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: MCP4017是一种数字电位器,它可以通过I2C总线进行编程控制。它具有一些使用程序例程的功能,这些例程可以帮助我们更好地理解和使用这个设备。 在使用MCP4017之前,我们需要了解一些基本的概念。首先,我们需要知道如何使用I2C总线和相应的地址来与MCP4017通信。其次,我们需要了解如何设置和读取电位器的值。 一个基本的MCP4017程序例程可以分为以下几个步骤: 1. 初始化I2C总线:我们需要初始化I2C总线,并确保MCP4017的地址正确配置。 2. 设置电位器的初始值:我们可以使用指令将电位器设置为一定的初始值,例如将电位器调节到一半的位置。 3. 读取电位器的当前值:我们可以使用指令从MCP4017中读取当前电位器的值,并将其显示出来。 4. 调整电位器的值:我们可以使用指令调整电位器的值,例如向上或向下调节电位器,以实现所需的电阻调节。 5. 循环执行程序:我们可以将上述的操作放入一个循环中,以实现连续的电位器控制功能。 在编写MCP4017程序例程时,我们还需要考虑一些其他的因素,例如错误处理、超时设置、通信稳定性等。 总之,MCP4017程序例程是一种帮助我们了解和使用MCP4017数字电位器的工具。通过编写和执行这些例程,我们可以更好地掌握数字电位器的控制方法,并将其应用于我们的项目中。 ### 回答2: MCP4017是一款数字电位器芯片,可以用于模拟电路中的调节电阻值。程序例程是指对于MCP4017这款芯片的控制和操作的代码实现。 MCP4017程序例程可以用不同的编程语言进行编写,如C语言、Arduino语言等,以下是一个示例的MCP4017程序例程: 首先,需要定义MCP4017芯片的引脚连接,将其与控制器连接,并声明所需的变量。然后,在程序的初始化部分,需要设置引脚的输入和输出模式,并初始化MCP4017芯片。 接下来,可以使用相应的代码来控制MCP4017芯片的操作。例如,可以使用digitalWrite函数将信号发送到MCP4017芯片的控制引脚,设置电阻的调节方向。使用analogWrite函数可以控制MCP4017芯片电阻值的大小,通过给定一个0到255之间的数值,来调整电阻值的大小。 在实际的应用中,可以根据需要设计更多的功能,如根据外部传感器的值来动态调整电阻值,或者通过串口通信从其他设备读取电阻值等等。这些可以通过在程序例程中添加适当的代码来实现。 最后,在循环部分,可以编写代码来连续更新MCP4017芯片的电阻值。循环内的延时函数可以用来控制电阻值调整的速度或频率。 总之,MCP4017程序例程是指对于MCP4017芯片的控制代码的实现。通过编写相应的程序,可以灵活地控制和调节MCP4017芯片的电阻值,以满足不同应用的需求。 ### 回答3: MCP4017是一款数字电位计,它具有四通道的输出和通过SPI接口进行通信的能力。MCP4017程序例程是使用该数字电位计进行控制和调节的示例程序。 在使用MCP4017之前,首先需要初始化SPI接口,并设置MCP4017的工作模式和通道数。接下来,可以通过SPI接口发送命令将所需的通道值写入到MCP4017的寄存器中。MCP4017的寄存器用于存储每个通道的输出值,可以通过修改这些寄存器的值来实现对相应通道的控制。 示例程序中可以使用循环结构和延时函数来控制MCP4017的输出值。可以通过循环将MCP4017的通道1输出值从最小值逐渐增加到最大值,然后再逐渐减小,实现递增和递减的功能。通过改变循环的次数和延时的时间,可以控制递增和递减的速度。 除了控制递增和递减,MCP4017还可以根据外部输入信号来调节输出值。示例程序中可以使用中断来监听外部输入信号的变化。当外部输入信号变化时,可以通过读取相应的输入状态来判断应该增加还是减小输出值。 总结来说,MCP4017程序例程是通过SPI接口控制MCP4017数字电位计的示例程序。通过修改寄存器的值和使用循环结构和延时函数,可以实现控制递增和递减以及根据外部输入信号调节输出值的功能。这些例程可以作为使用MCP4017的参考,帮助开发者理解和使用该数字电位计。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会编程的小江江

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值