这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【EFM8BB52单片机】数据采集系统(暂时完结)

共18条 1/2 1 2 跳转至

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

助工
2021-12-22 11:50:43   被打赏 50 分(兑奖)     打赏

    开箱贴  +系统框图


框图捕获.PNG

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

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

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

1640145027845721.jpg

1640145027420824.jpg

走线1.jpg走线2.jpg


哈哈.jpg





关键词: 单片机     MCU     BB52     数据采集    

助工
2021-12-22 11:51:43     打赏
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:52     打赏
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:09     打赏
4楼

焊接图,


焊接图1.jpg

焊接图2.jpg



焊接图3.jpg





助工
2021-12-22 11:52:20     打赏
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<len;t++)
    {
        temp=(num/oled_pow(10,len-t-1))%10;
        if(enshow==0&&t<(len-1))
        {
          if(temp==0)
          {
            OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
            continue;
          }else enshow=1;

        }
        OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2);
    }
}


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:35     打赏
6楼


五楼:深夜完结,

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

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


程序连接:CaiJi.zip

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


专家
2021-12-22 12:58:36     打赏
7楼

6楼


高工
2021-12-22 15:03:01     打赏
8楼

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


专家
2021-12-22 15:05:56     打赏
9楼

感谢楼主的分享


专家
2021-12-22 15:08:34     打赏
10楼

感谢楼主的分享


共18条 1/2 1 2 跳转至

回复

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