论坛» 活动中心» 板卡试用

【EFM8BB52单片机】数据采集系统(暂时完结)

助工
2021-12-22 11:50 1楼

开箱贴 +系统框图


框图捕获.PNG

由于年底了,大家好像这个月都很忙,慌得不行,给金主和EEPW说声抱歉。只能先开个箱了,先占个楼,手头的活处理完,马上开始这个项目。

先开箱,快递拿到了,刚开始群里说可能不安全,一直也没拆快递,想着放几天就安全了,快递一直在桌子上放着,今天中午刚打开快递的箱子。不愧是大厂,片子包装的非常安全,不仅有防静电的袋子,而且里三层外三层,多图预警:

又仔细看了看板子的走线,横平竖直(大厂的feel),也更像一个MCU,还有元器件的摆放,真的是恰到好处。元器件也不像平时自己的选材(自己选材越大越好,方便自己焊接,但是元器件小了,更节省空间了,也更袖珍了),给开发人员一种不一样的赶脚,手动比心ღ( ´・ᴗ・` )比心。

1640145027845721.jpg

1640145027420824.jpg

走线1.jpg走线2.jpg


哈哈.jpg


助工
2021-12-22 11:51 2楼

二:点灯走起

哈哈2.png

首先祝大家元旦快乐,2022年新的一年,就从点灯开始吧。昨天吃饱了,睡好了,今天就开始玩板子啦。环境的搭建就不说了,前面很多大佬讲的很详细了,给各位大佬比个心。先大概了解一下板子的电路图,俗话说:“工欲先其事,必先利其器”。电路图对我们以后的开发还是比较重要的,如下图。

52单片机电路图.png

整体的布局和传统的51单片机差不多的,一共四组IO口供开发者使用。本数据采集系统就是以EFM8BB52为核心控制器,是系统的数据处理中心,电路中各个部分要想进行使用都需要使用单片机先进行数据的处理,并把处理好的数据返回到原先的电路



接着就是点灯电路了,开发板上有两个灯,一黄,一蓝。黄色灯是LED0,蓝色灯是J-Link连接的灯。黄色灯的电路图如下:由图可知,连接的是P1.4,接下来写程序,就是操作P1.4了。

点灯电路图.png

接着就是激动人心的时刻了,小灯开始闪烁了。为了更加明显,又配了一个小灯,二者做了一下对比,效果是差不多的。

QQ动图.gif

QQ图片123.gif


助工
2021-12-22 11:51 3楼

三,SPI口的使用


SPI的实现方式有两种,硬件实现和软件实现,本采样系统采用软件实现,也就是IO口模拟SPI协议。下面是手册的说明,具体的介绍本芯片的SPI的具体情况。SPI是单片机与采样模块之间的通信协议,单片机作为主机,采样模块作为从机来进行通信。主机发送命令,而从机是接收命令,返回数据的。

SPI.png


下面是翻译。

****************************************************************************/

串行外围接口(SPI0)


串行外围接口(SPI)模块提供对灵活的fll双工同步串行总线的访问。SPI可以作为

3线或4线模式下的主(时钟驱动器)或辅助(时钟接收器)接口,并支持多个主/辅助设备-

ces在单个SPI总线上。芯片选择(NSS)信号可配置为在二次模式下选择SPI或禁用SPI的输入

在具有多个主接口的环境中的主模式操作,避免了在多个主接口时SPI总线上的争用

设备尝试同时传输数据。NSS也可以在主界面中配置为固件控制的芯片选择输出

模式,或禁用以减少所需的管脚数。其他通用端口L/O引脚可用于选择多个secon

戴瑞装置。


●支持3线或4线主或辅助接口模式

●在任一模式下支持高达12 Mbps的外部时钟频率

●支持所有时钟相位和极性模式

●8位可编程时钟速率(主)

●可编程接收超时(辅助)

●发送和接收时的四字节FIFO

●在同一数据线上支持多个主接口

****************************************************************************/

下图是SPI的四个接口,SCLK,MISO,MOSI,CS等四个脚,这几个脚很关键,实现数据采集就靠他们了。

SPI的端口配置.png

顺便说一下采样的原理,没用过的小伙伴可以看一下,用过的就跳过就行了。ADC的采样原理,ADC把模拟量变为数字量,用数字量近似表示模拟量,这个过程称为量化。量化误差是ADC的有限位数对模拟量进行量化而引起的误差。实际上,要准确表示模拟量,ADC的位数需很大甚至无穷大。一个分辨率有限的ADC的阶梯状转换特性曲线与具有无限分辨率的ADC转换特性曲线(直线)之间的最大偏差即是量化误差。如下图,

image.png

****************************************************************************/

本系统用的AD模块是XPT2046,一共有四个通道,本系统用其中两个通道。如下图,可以看出它的具体的接线方式,还有具体的通道。要把它玩起来,还需要了解它的时序,如下图,有具体的四根线的时序图,接下来就是程序了,如下图

XP2046采样模块.png

SPI芯片.png

/****************************************************************************


#include"XPT2046.h" /**************************************************************************** *函数名:SPI_Write *输 入:dat:写入数据 *输 出:无 *功 能:使用SPI写入数据 ****************************************************************************/ void SPI_Write(uchar dat) { uchar i; CLK = 0; for(i=0; i<8; i++) { DIN = dat >> 7; //放置最高位 dat <<= 1; CLK = 0;//上升沿放置数据 CLK = 1; } } /**************************************************************************** *函数名:SPI_Read *输 入:无 *输 出:dat:读取 到的数据 *功 能:使用SPI读取数据 ****************************************************************************/ uint SPI_Read(void) { uint i, dat=0; CLK = 0; for(i=0; i<12; i++)//接收12位数据 { dat <<= 1; CLK = 1; CLK = 0; dat |= DOUT; } return dat; } /**************************************************************************** *函数名:Read_AD_Data *输 入:cmd:读取的X或者Y *输 出:endValue:最终信号处理后返回的值 *功 能:读取触摸数据 ****************************************************************************/ uint Read_AD_Data(uchar cmd) { uchar i; uint AD_Value; CLK = 0; CS = 0; SPI_Write(cmd); for(i=6; i>0; i--); //延时等待转换结果 CLK = 1; //发送一个时钟周期,清除BUSY _nop_(); _nop_(); CLK = 0; _nop_(); _nop_(); AD_Value=SPI_Read(); CS = 1; return AD_Value; }




助工
2021-12-22 11:52 4楼

焊接图,


焊接图1.jpg

焊接图2.jpg



焊接图3.jpg




助工
2021-12-22 11:52 5楼

四楼:点亮OLED,显示具体的数据

OLED采用IIC通讯,一共有四个引脚,使用方便,其中最重要的就是SDA,SCL,两个通讯的脚,一个是数据传输脚,另外一个是时钟引脚,很好用。此外,电压也要注意,我一般接3.3V(感觉太高容易烧坏,惨痛的教训,ADC模块刚被烧坏了,感觉有一点怪味,然后就坏了,打算再买一个),也可以接5V的,。还有7脚的OLED,不推荐使用。



还有在使用时要注意两个函数的区别,就是显示字符的函数,还有就是显示采集数据值的函数,我们本实验 要用的是显示采集数据值的函数,不要弄错了。因为刚开始我弄错了


OLED_ShowNum(56,4,temp,1,16); //温度整数t void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2) { u8 t,temp; u8 enshow=0; for(t=0;t
        


OLED.jpg


温度传感器的使用,具体的就是数据的换算的方式,以及接线方式,还有具体的读函数,以及延时函数,最重要的是US级的延时函数,在实验中,自己的延时函数不准,导致采集数据不对。由于EFMBB52单片机的系统频率是24.5Mhz,因此它的延时函数和传统的51单片机的延时函数不一样,这一点要注意。下面也写了一个延时函数供大家参考。

连接方式,VCC3.3VIO口接P1.4,最好加一个上拉电阻,程序如下,深夜码字,可能会有一些问题,大家体谅。此时室内温度大概6度,不知道为什么屏幕的小数没有显示出来,明天再仔细看看。


SI_SBIT(DSPORT,SFR_P1,4); void Delay1us() //@24.5MHz { unsigned char i; _nop_(); _nop_(); _nop_(); i = 3; while (--i); } void Delay1ms() //@24.5MHz { unsigned char i, j; i = 24; j = 210; do { while (--j); } while (--i); } /******************************************************************************* * 函 数 名 : Ds18b20Init * 函数功能 : 初始化 * 输 入 : 无 * 输 出 : 初始化成功返回1,失败返回0 *******************************************************************************/ uchar Ds18b20Init() { uchar i; DSPORT = 0; //将总线拉低480us~960us i = 70; while(i--);//延时642us DSPORT = 1; //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低 i = 0; while(DSPORT) //等待DS18B20拉低总线 { Delay1ms(1); i++; if(i>5)//等待>5MS { return 0;//初始化失败 } } return 1;//初始化成功 } /******************************************************************************* * 函 数 名 : Ds18b20WriteByte * 函数功能 : 向18B20写入一个字节 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Ds18b20WriteByte(uchar dat) { uint i, j; for(j=0; j<8; j++) { DSPORT = 0; //每写入一位数据之前先把总线拉低1us i++; // DSPORT = dat & 0x01; //然后写入一个数据,从最低位开始 i=6; while(i--); //延时68us,持续时间最少60us DSPORT = 1; //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值 dat >>= 1; //右移,循环八次,写字节 } } /******************************************************************************* * 函 数 名 : Ds18b20ReadTemp * 函数功能 : 读取温度 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ int Ds18b20ReadTemp() { int temp = 0; uchar tmh, tml; Ds18b20ChangeTemp(); //先写入转换命令 Ds18b20ReadTempCom(); //然后等待转换完后发送读取温度命令 tml = Ds18b20ReadByte(); //读取温度值共16位,先读低字节 tmh = Ds18b20ReadByte(); //再读高字节 temp = tmh; temp <<= 8; temp |= tml; return temp; } /******************************************************************************* * 函 数 名 : datapros() * 函数功能 : 温度读取处理转换函数 * 输 入 : temp * 输 出 : 无 *******************************************************************************/ void datapros(int temp) { float tp; if(temp< 0) //当温度值为负数 { DisplayData[0] = 0x40; // - //因为读取的温度是实际温度的补码,所以减1,再取反求出原码 temp=temp-1; temp=~temp; tp=temp; temp=tp*0.0625*100+0.5; //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点 //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就 //算加上0.5,还是在小数点后面。 } else { DisplayData[0] = 0x00; tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量 //如果温度是正的那么,那么正数的原码就是补码它本身 temp=tp*0.0625*100+0.5; //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点 //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就 //算加上0.5,还是在小数点后面。 } }

温度.jpg




助工
2021-12-22 11:52 6楼


五楼:深夜完结,

数据采集系统完结,由于AD模块晚上调的时间电压太大烧坏了,明天回购一个。

先放一个程序和视频的连接,由于快放假了,有点小忙,等假期再完善一下。


程序连接:CaiJi.zip

视频连接:【EFM8BB52-数据采集系统-哔哩哔哩】https://b23.tv/AAfKD3P

高工
2021-12-22 12:58 7楼

6楼

高工
2021-12-22 15:03 8楼

感谢楼主的分享,很实用了。

专家
2021-12-22 15:05 9楼

感谢楼主的分享

专家
2021-12-22 15:08 10楼

感谢楼主的分享

共18条 1/2 1 2 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]