单片机/MCU论坛
直播中

小浩编程

3年用户 16经验值
擅长:嵌入式技术
私信 关注
[文章]

【RA4M2设计挑战赛】通过ADC采集温湿度通过IIC传输到OLED显示屏

理论介绍及接线

接线的主体情况如下图,R7作为主机通过IIC与OLED屏幕从机进行通信,将ADC采集的模拟数据通过芯片内部进行数模转换并通过IIC发送到屏幕上。

11195430b1e40f09a397d250935adc2.jpg

在本次的实验中主要用到了两个外设,一个是ADC,另一个是IIC,接下来分开介绍一下。

ADC

ADC是Analog-to-Digital Converter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。

1、ADC的作用

采集传感器的数据,测量输入电压,检查电池电量剩余,监测温湿度等。

典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。

poYBAGLjmCyAfiQMAAA9kUe0n4c145.png

2、ADC的性能指标

量程:能测量的电压范围

分辨率:ADC的分辨率通常以输出二进制数的位数表示,位数越多,分辨率越高,一般来说分辨率越高,转化时间越长。

转化时间:模拟输入电压在允许的最大变化范围内,从转换开始到获得稳定的数字量输出所需要的时间称为转换时间
3、电压输入范围

ADC 输入范围为:V REF- ≤ V IN ≤ V REF+ 。由 V REF- 、V REF+ 、V DDA 、V SSA 、这四个外部引脚决定。

我们在设计原理图的时候一般把 V SSA 和 V REF- 接地,把 V REF+ 和 V DDA 接 3.3V,得到ADC的输入电压范围为:0~3.3V

如果我们想让输入的电压范围变宽,去到可以测试负电压或者更高的正电压,我们可以在外部加一个电压调理电路,把需要转换的电压抬升或者降压到0~3.3V,这样 ADC 就可以测量了

IIC

IIC是很常用的一种总线协议,IIC是NXP公司设计的,IIC使用两条线在主控制器和从机之间进行数据通信。一条是SCL(串行时间线),另一条是SDA(串行数据线),这两条数据线需要上拉电阻,总线空闲的时候SCL和SDA处于高电平。
IIC总线标准模式下速度可以达到100Kb/s,快速模式下可以达到400Kb/s。IIC总线工作是按一定的协议来运行的。

IIC是支持多从机的,也就是一个IIC控制器下可以挂多个IIC从设备,这些不同的IIC从设备有不同的器件地址,这样IIC主控制器就可以通过IIC设备的器件地址访问指定的IIC设备了,一个IIC总线连接多个IIC设备如下图:
上图中SDA和SCL这两根线必须要接一个上接电阻,一般是4.7K。其余的IIC从器件都挂接到SDA和SCL这两根线上,这样就可以通过SDA和SCL这两根线来访问多个IIC设备。

相关术语:
1,起始位
顾名思义,也就是IIC通信起始标志,通过这个起始位就可以告诉IIC从机,“我”要开始进行IIC通信了。在SCL为高电平时,SDA出现下降沿就表示为起始位,如下图:

2,停止位
停止位就是停止IIC通信的标志位,和起始位的功能相反。在SCL为高电平的时候,SDA出现上升沿就表示停止位,如下图:

3,数据传输
IIC总线在数据传输的时候要保证在SCL高电平期间,SDA上的数据稳定,因此SDA上的数据变化只能在SCL低电平期间发生,如下图:

4,应答信号
当IIC主机发送完8位数据以后会将SDA设置为输入状态,等待IIC从机应答,也就是等到IIC从机告诉主机它接收到数据了。应答信号是由从机发出的,主机需要提供应答信号所需的时钟,主机发送完8位数据以后紧跟着的一个时钟信号就是应答信号使用的。从机通过将SDA拉低来表示发出应答信号,表示通信成功,否则表示通信失败。

5,IIC写时序
主机通过IIC总线与从机之间进行通信不外乎两个操作:写和读。IIC总线总字节写时序如下图:

具体步骤:
1)、开始信号。
2)、发送IIC设备地址,每个IIC器件都有一个设备地址,通过发送具体的设备地址来决定访问哪个IIC器件。这是一个8位的数据,其中高7位是设置地址,最后1位是读写位,为1的话表示这是一个读操作,为0的话表示这是一个写操作。
3)、IIC器件地址后面跟着一个读写位,为0表示写操作,为1表示读操作。
4)、从机发送的ACK应答信号。
5)、重新发送开始信号。
6)、发送要写入数据的寄存器地址。
7)、从机发送的ACK应答信号。
8)、发送要写入寄存器的数据。
9)、从机发送的ACK应答信号。
10)、停止信号。

配置

将引脚配置成ADC和IIC

poYBAGLjmc2AfFQaAACpH5F4x-Y256.png
时钟配置
pYYBAGLjmhOAHnVuAAFe5Y3Hutw321.png

敲代码

然后官方历程里也有例程,将其移植一下就好啦,官方真的很NICE
image.png

#include "hal_data.h"

FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER


* main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
* is called by main() when no RTOS is used.

volatile bool scan_complete_flag = false;
void adc_callback (adc_callback_args_t * p_args)
{
FSP_PARAMETER_NOT_USED(p_args);
scan_complete_flag = true;
}

double a0;
uint16_t adc_data1=0;
//uint16_t adc_data2=0;

void hal_entry(void)
{
/* TODO: add your own code here */

fsp_err_t err = FSP_SUCCESS;
/* Initializes the module. */
err = R_ADC_Open(&g_adc0_ctrl, &g_adc0_cfg);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);

/* Enable channels. */
err = R_ADC_ScanCfg(&g_adc0_ctrl, &g_adc0_channel_cfg);
assert(FSP_SUCCESS == err);

while(1)
{

/* Enable scan triggering from ELC events. */
(void) R_ADC_ScanStart(&g_adc0_ctrl);
scan_complete_flag = false;
while (!scan_complete_flag)
{
/* Wait for callback to set flag. */
}
err =R_ADC_Read(&g_adc0_ctrl, ADC_CHANNEL_0, &adc_data1);
assert(FSP_SUCCESS == err);
a0=(adc_data1/4095.0)*3.3;

err =R_ADC_Read(&g_adc0_ctrl, ADC_CHANNEL_5, &adc_data2);

assert(FSP_SUCCESS == err);
a5=(adc_data1/4095.0)*3.3;
R_BSP_SoftwareDelay (20, BSP_DELAY_UNITS_MILLISECONDS);
}

#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}

效果展示

两整天的成果,希望能够帮到你,收工

更多回帖

发帖
×
20
完善资料,
赚取积分