学习 学习
因为后面需要用到OLED屏幕显示,这里就开始了整合之路,没有新东西。就像变形金刚里的大力神一样进行组合变形。只是这里遇到一个问题,还是搞不明白,在程序烧录进去后功能没问题。重新上电后需要重启才开始运行。很费解。工程文件在这里 UART_OLED.rar
串口1的调试
该MCU共有2个串口,即串口0和串口1.这两个串口在结构上是不同的,因此在使用方法上也是不同。首先在结构上,串口0需要定时器来为其产生波特率,而串口1则内部有自己的定时器可以直接自己产生波特率。串口0内部没有FIFO,而串口1拥有发送和接收FIFO,可以提高使用效率。除此之外,串口1在发送和接收数据时数据格式除了正常串口的起始位,奇偶校验位,停止位等外,还可以配置extra bit。如果配置了extra bit则可以不用FIFO。不过为了方便使用,这里调试还是采用FIFO,不配置extra bit。
关于FIFO
发送和接收FIFO都可以触发中断,对于发送FIFO,寄存器TXTH充当FIFO数据的最低标准,,并且当FIFO中的字节数小于或等于TXTH值时,将设置TXRQ标志。例如,如果TXTH字段配置为1,则在传输FIFO中剩余0或1个字节发送时,TXRQ将被设置。并且寄存器UART1FCT当发送结束后,会自动变成0,该寄存器用来指示发送FIFO中有多少个字节的数据
对于接收FIFO,RXTH充当FIFO数据的高水位线,并且RXRQ标志将在FIFO中的字节数大于RXTH值时设置。例如,如果RXTH字段配置为0,则RXRQ将在接收FIFO中至少有一个字节时设置。同样,当数据读取后,UART1FCT用来指示接收FIFO中有多少个数据的值会自动变成0.
串口初始化
查看官方例程,对于UART1的BSP驱动包含很多函数,而在本工程中用到串口1仅仅用作发送功能,因此这里只使用串口的发送功能,发送依旧采用中断发送,如果不采用中断,如果一次性发送多个数据,接收端只能收到开始和结束的数据。
串口的IO口初始化
该MCU的片内外设对于IO的映射比较灵活,当需要将片内外设映射到外部IO口时,需要根据片内外设的优先级映射到从0.0开始的IO。其中UART0如果使用,则固定映射到0.4和0.5,其他外设则按照如图1所示进行映射。如果想将某一外设移动其按照优先级本应该映射到的IO口,则只需要将其本应该映射到的IO口skip就可以。例如,如果只使用UART1的功能,则其应该映射到0.4和0.5,如果想映射到0.6和0.7,则只需要将P1SKIP寄存器的第4位和第5位设置成skip即可。

IO口初始化代码如下:
void uart1_io_set(void)
{
//将串口1映射到0.6,0.7
P0MDOUT = P0MDOUT_B0__OPEN_DRAIN | P0MDOUT_B1__OPEN_DRAIN
| P0MDOUT_B2__OPEN_DRAIN | P0MDOUT_B3__OPEN_DRAIN
| P0MDOUT_B4__PUSH_PULL | P0MDOUT_B5__OPEN_DRAIN
| P0MDOUT_B6__PUSH_PULL | P0MDOUT_B7__OPEN_DRAIN;
//0.6.0.7设置为数字模式
P0MDIN = P0MDIN_B0__ANALOG | P0MDIN_B1__ANALOG | P0MDIN_B2__ANALOG
| P0MDIN_B3__ANALOG | P0MDIN_B4__DIGITAL | P0MDIN_B5__DIGITAL
| P0MDIN_B6__DIGITAL | P0MDIN_B7__DIGITAL;
//将P0.4 P0.5跳过
P0SKIP = P0SKIP_B0__SKIPPED | P0SKIP_B1__SKIPPED | P0SKIP_B2__SKIPPED
| P0SKIP_B3__SKIPPED | P0SKIP_B4__SKIPPED
| P0SKIP_B5__SKIPPED | P0SKIP_B6__NOT_SKIPPED
| P0SKIP_B7__NOT_SKIPPED;
}对于波特率,以及中断的配置
这里将波特率设置为115200,注意前提是系统时钟为内部时钟(24.5MHZ)的8分频,这里需要配置串口1内部自己的定时器的装载值。为了发送数据方便,这里对FIOF的设置阈值均为0.具体程序如下。
void uart1_param_init(void)
{
SFRPAGE = 0x20;
//使能内部定时器
SBCON1 = SBCON1_BREN__ENABLED | SBCON1_BPS__DIV_BY_1;
//设置FIFO阈值为0
UART1FCN0 = UART1FCN0_RXTH__ZERO | UART1FCN0_TXTH__ZERO
| UART1FCN0_RFRQE__ENABLED | UART1FCN0_TFRQE__DISABLED;
//设置内部定时器装载值
SBRLH1 = (0xFF << SBRLH1_BRH__SHIFT);
SBRLL1 = (0xF3 << SBRLL1_BRL__SHIFT);
//使能接收
SCON1 |= SCON1_REN__RECEIVE_ENABLED;
UART1PCF=UART1PCF_RXSEL__CROSSBAR;
SMOD1=SMOD1|SMOD1_SDL__8_BITS|SMOD1_SBL__SHORT|SMOD1_PE__PARITY_DISABLED | SMOD1_XBE__DISABLED|SMOD1_SPT__ODD_PARITY|SMOD1_MCE__MULTI_DISABLED;
UART1FCN1 &= ~(UART1FCN1_RIE__BMASK | UART1FCN1_TIE__BMASK);
//接收空闲中断为16个时钟周期
UART1FCN1 |= UART1FCN1_RXTO__TIMEOUT_16;
}
//对发送FIFO进行设置
void UART1_initTxFifo(void)
{
SFRPAGE = 0x20;
UART1FCN0 &= ~(UART1FCN0_TFRQE__BMASK
| UART1FCN0_TFLSH__BMASK
| UART1FCN0_TXTH__FMASK
| UART1FCN0_TFRQE__BMASK);
//禁止发送中断
UART1FCN0 |= (UART1FCN0_TXTH__ZERO | UART1FCN0_TFRQE__DISABLED);
UART1FCN1 &= ~(UART1FCN1_TFRQ__BMASK
| UART1FCN1_TXHOLD__BMASK
| UART1FCN1_TXNF__BMASK
| UART1FCN1_TIE__BMASK);
UART1FCN1 |= (UART1FCN1_TFRQ__SET
| UART1FCN1_TXHOLD__CONTINUE
| UART1FCN1_TIE__DISABLED);
}发送数据代码,利用UART1_wrteBuffer函数来使能发送中断
void UART1_writeBuffer(uint8_t buffer, uint8_t length)
{
// Initialize internal data
txBuffer = buffer;
txRemaining = length;
// Enable tx fifo interrupts to kick off transfer
UART1FCN0 |= UART1FCN0_TFRQE__ENABLED;
}
SI_INTERRUPT(UART1_ISR, UART1_IRQn)
{
if ((UART1FCN1 & UART1FCN1_TFRQ__BMASK) && (UART1FCN0 & UART1FCN0_TFRQE__ENABLED))
{
// Write bytes as long as the tx fifo is not full and there
// is room in the tx buffer
while (txRemaining && (UART1FCN1 & UART1FCN1_TXNF__NOT_FULL))
{
SBUF1 = txBuffer;
--txRemaining;
}
}
}源工程文件点击这里UART1_SEND.rar
因为系统需要OLED屏幕作为显示,所以这里先将OLED屏幕显示点亮来作为第二个任务。点灯的程序参考shihengrui的帖子成功点亮,再此对其表示感谢。
OLED屏幕选择的是0.96英寸的OLED屏幕,采用的通信方式是IIC,这里依旧选择软件模拟的方式来进行点亮显示。
话不多说,直接上代码,只不过在进行存字库字符的时候,由于该板子的内存比较小,这里将字库的数组前都加上“data”关键字,以将数据放到data段,否则会报错。还有一个问题需要注意,采用Simplicity Studio编译器进行编译程序,需要添加licence,否则会提示超出版本程序大小限制
OLED头文件
#ifndef INC_OLED_H_ #define INC_OLED_H_ #include <SI_EFM8BB52_Register_Enums.h> #define OLED_CMD 0 //写命令 #define OLED_DATA 1 //写数据 #define OLED_MODE 0 //定义端口 SI_SBIT(OLED_SCL,SFR_P1,5); SI_SBIT(OLED_SDA,SFR_P1,6); #define OLED_SCLK_Clr() OLED_SCL=0 #define OLED_SCLK_Set() OLED_SCL=1 #define OLED_SDIN_Clr() OLED_SDA=0 #define OLED_SDIN_Set() OLED_SDA=1 #define SIZE 16 #define XLevelL 0x02 #define XLevelH 0x10 #define Max_Column 128 #define Max_Row 64 #define Brightness 0xFF #define X_WIDTH 128 #define Y_WIDTH 64 #define u8 uint8_t #define u32 uint32_t #define u16 uint16_t //OLED控制用函数 void OLED_WR_Byte(unsigned dat,unsigned cmd); void OLED_Display_On(void); void OLED_Display_Off(void); void OLED_Init(void); void OLED_Clear(void); void OLED_DrawPoint(u8 x,u8 y,u8 t); void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot); void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size); void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size); void OLED_ShowString(u8 x,u8 y, u8 *p,u8 Char_Size); void OLED_Set_Pos(unsigned char x, unsigned char y); void OLED_ShowCHinese(u8 x,u8 y,u8 no); void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[]); void Delay_50ms(unsigned int Del_50ms); void Delay_1ms(unsigned int Del_1ms); void fill_picture(unsigned char fill_Data); void Picture(); void IIC_Start(); void IIC_Stop(); void Write_IIC_Command(unsigned char IIC_Command); void Write_IIC_Data(unsigned char IIC_Data); void Write_IIC_Byte(unsigned char IIC_Byte); void IIC_Wait_Ack(); #endif /* INC_OLED_H_ */
OLED源文件
/*
* oled.c
*
* Created on: 2021年12月20日
* Author: liubinbin
*/
#include "oled.h"
#include "oledfont.h"
#include <device.h>
/**
* @name:IIC_Start()
* @msg: I2C发送起始信号
* @param {*}
* @return {*}
*/
void IIC_Start()
{
OLED_SCLK_Set() ;
NOP();NOP();NOP(); //等待延时
OLED_SDIN_Set();
NOP();NOP();NOP(); //等待延时
OLED_SDIN_Clr();
NOP();NOP();NOP(); //等待延时
OLED_SCLK_Clr();
NOP();NOP();NOP(); //等待延时
}
/**
* @name: void IIC_Stop()
* @msg: IIC停止信号
* @param {*}
* @return {*}
*/
void IIC_Stop()
{
OLED_SCLK_Set() ;
NOP();NOP();NOP(); //等待延时
OLED_SDIN_Clr();
NOP();NOP();NOP(); //等待延时
OLED_SDIN_Set();
NOP();NOP();NOP(); //等待延时
}
/**
* @name:void IIC_Wait_Ack()
* @msg: 等待应答
* @param {*}
* @return {*}
*/
void IIC_Wait_Ack()
{
OLED_SCLK_Set() ;
NOP();NOP();NOP();
OLED_SCLK_Clr();
NOP();NOP();NOP();
}
/**
* @name: Write_IIC_Byte(unsigned char IIC_Byte)
* @msg: IIC写一个字节数据
* @param {unsigned char} IIC_Byte
* @return {*}
*/
void Write_IIC_Byte(unsigned char IIC_Byte)
{
unsigned char i;
unsigned char m,da;
da=IIC_Byte;
NOP();NOP();NOP();
OLED_SCLK_Clr();
NOP();NOP();NOP();
for(i=0;i<8;i++)
{
m=da;
OLED_SCLK_Clr();
m=m&0x80;
if(m==0x80)
{OLED_SDIN_Set();}
else OLED_SDIN_Clr();
NOP();NOP();NOP();
da=da<<1;
OLED_SCLK_Set();
NOP();NOP();NOP();
OLED_SCLK_Clr();
NOP();NOP();NOP();
}
}
/**
* @name:Write_IIC_Command(unsigned char IIC_Command)
* @msg: IIC写一个命令
* @param {unsigned char} IIC_Command
* @return {*}
*/
void Write_IIC_Command(unsigned char IIC_Command)
{
IIC_Start();
Write_IIC_Byte(0x78);
IIC_Wait_Ack();
Write_IIC_Byte(0x00);
IIC_Wait_Ack();
Write_IIC_Byte(IIC_Command);
IIC_Wait_Ack();
IIC_Stop();
}
/**
* @name: Write_IIC_Data(unsigned char IIC_Data)
* @msg: IIC写一个数据
* @param {unsigned char} IIC_Data
* @return {*}
*/
void Write_IIC_Data(unsigned char IIC_Data)
{
IIC_Start();
Write_IIC_Byte(0x78); //D/C#=0; R/W#=0
IIC_Wait_Ack();
Write_IIC_Byte(0x40); //write data
IIC_Wait_Ack();
Write_IIC_Byte(IIC_Data);
IIC_Wait_Ack();
IIC_Stop();
}
/**
* @name: OLED_WR_Byte(unsigned dat,unsigned cmd)
* @msg: OLED写一个字节
* @param {unsigned} dat 写数据
* @param {unsigned} cmd 写命令
* @return {*}
*/
void OLED_WR_Byte(unsigned dat,unsigned cmd)
{
if(cmd)
{
Write_IIC_Data(dat);
}
else
{
Write_IIC_Command(dat);
}
}
/**
* @name:fill_picture(unsigned char fill_Data)
* @msg: 填充图片
* @param {unsigned char} fill_Data
* @return {*}
*/
void fill_picture(unsigned char fill_Data)
{
unsigned char m,n;
for(m=0;m<8;m++)
{
OLED_WR_Byte(0xb0+m,0); //page0-page1
OLED_WR_Byte(0x00,0); //low column start address
OLED_WR_Byte(0x10,0); //high column start address
for(n=0;n<128;n++)
{
OLED_WR_Byte(fill_Data,1);
}
}
}
/**
* @name:OLED_Set_Pos(unsigned char x, unsigned char y)
* @msg: 设置坐标
* @param {unsigned char} x 横坐标
* @param {unsigned char} y 纵坐标
* @return {*}
*/
void OLED_Set_Pos(unsigned char x, unsigned char y)
{
OLED_WR_Byte(0xb0+y,OLED_CMD);
OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
OLED_WR_Byte((x&0x0f),OLED_CMD);
}
/**
* @name: OLED_Display_On(void)
* @msg: 开启OLED屏幕显示
* @param {*}
* @return {*}
*/
void OLED_Display_On(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令
OLED_WR_Byte(0X14,OLED_CMD); //DCDC ON
OLED_WR_Byte(0XAF,OLED_CMD); //DISPLAY ON
}
/**
* @name: OLED_Display_Off(void)
* @msg: 关闭OLED显示
* @param {*}
* @return {*}
*/
void OLED_Display_Off(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令
OLED_WR_Byte(0X10,OLED_CMD); //DCDC OFF
OLED_WR_Byte(0XAE,OLED_CMD); //DISPLAY OFF
}
/**
* @name: OLED_Clear(void)
* @msg: 清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样
* @param {*}
* @return {*}
*/
void OLED_Clear(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7)
OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址
OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址
for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); //更新显示
}
}
/**
* @name:OLED_On(void)
* @msg: 打开OLED显示
* @param {*}
* @return {*}
*/
void OLED_On(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7)
OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址
OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址
for(n=0;n<128;n++)OLED_WR_Byte(1,OLED_DATA); //更新显示
}
}
/**
* @name:OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
* @msg: 显示字符
* @param {u8} x 起始横坐标0-128
* @param {u8} y 起始纵坐标0-6
* @param {u8} chr 显示字符
* @param {u8} Char_Size 大小12/16
* @return {*}
*/
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
{
unsigned char c=0,i=0;
c=chr-' ';//得到偏移后的值
if(x>Max_Column-1){x=0;y=y+2;}
if(Char_Size ==16)
{
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
}
else {
OLED_Set_Pos(x,y);
for(i=0;i<6;i++)
OLED_WR_Byte(F6x8[c][i],OLED_DATA);
}
}
/**
* @name: oled_pow(u8 m,u8 n)
* @msg: m的n次方
* @param {u8} m
* @param {u8} n
* @return {*}
*/
u32 oled_pow(u8 m,u8 n)
{
u32 result=1;
while(n--)result*=m;
return result;
}
/**
* @name: OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2)
* @msg: 显示数字
* @param {u8} x 起始横坐标0-128
* @param {u8} y 起始纵坐标0-6
* @param {u32} num 数字值
* @param {u8} len 位数
* @param {u8} size2 大小12/16
* @return {*}
*/
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);
}
}
/**
* @name: OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
* @msg: 显示字符串
* @param {u8} x起始横坐标0-128
* @param {u8} y起始纵坐标0-6
* @param {u8} *chr 字符串指针
* @param {u8} Char_Size 大小12/16
* @return {*}
*/
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
{
unsigned char j=0;
while (chr[j]!='\0')
{ OLED_ShowChar(x,y,chr[j],Char_Size);
x+=8;
if(x>120){x=0;y+=2;}
j++;
}
}
/**
* @name: OLED_Init(void)
* @msg: 初始化OLED屏幕
* @param {*}
* @return {*}
*/
void OLED_Init(void)
{
uint8_t SFRPAGE_save = SFRPAGE;
//init oled io
P1MDIN = P1MDIN|P1MDIN_B5__DIGITAL|P1MDIN_B6__DIGITAL;
P1MDOUT = P1MDOUT|P1MDOUT_B5__PUSH_PULL|P1MDOUT_B6__PUSH_PULL;
XBR2 = XBR2|XBR2_XBARE__ENABLED;
SFRPAGE = SFRPAGE_save;
OLED_WR_Byte(0xAE,OLED_CMD);//--display off
OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
OLED_WR_Byte(0x40,OLED_CMD);//--set start line address
OLED_WR_Byte(0xB0,OLED_CMD);//--set page address
OLED_WR_Byte(0x81,OLED_CMD); // contract control
OLED_WR_Byte(0xFF,OLED_CMD);//--128
OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap
OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverse
OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty
OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction
OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset
OLED_WR_Byte(0x00,OLED_CMD);//
OLED_WR_Byte(0xD5,OLED_CMD);//set osc division
OLED_WR_Byte(0x80,OLED_CMD);//
OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode off
OLED_WR_Byte(0x05,OLED_CMD);//
OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period
OLED_WR_Byte(0xF1,OLED_CMD);//
OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion
OLED_WR_Byte(0x12,OLED_CMD);//
OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh
OLED_WR_Byte(0x30,OLED_CMD);//
OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable
OLED_WR_Byte(0x14,OLED_CMD);//
OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
}测试main函数
int main (void)
{
u8 t1;
u8 t2;
sys_init();
OLED_Init();
IE_EA=0;
LED=0;
t1=0;
t2=' ';
OLED_Clear();
OLED_ShowChar(0,0,'E',16);
OLED_ShowChar(8,0,'E',16);
OLED_ShowChar(16,0,'P',16);
OLED_ShowChar(24,0,'W',16);
OLED_ShowChar(32,0,'.',16);
OLED_ShowChar(40,0,'C',16);
OLED_ShowChar(48,0,'O',16);
OLED_ShowChar(56,0,'M',16);
OLED_ShowString(64,0,".CN",16);
OLED_ShowString(0,2,"NUMBER:",16);
OLED_ShowString(0,4,"ASCALL:",16);
while (1)
{
OLED_ShowNum(56,2,t1,3,16);
OLED_ShowChar(56,4,t2,16);
LED=!LED;
t1++;
if(t1>255) t1=0;
t2++;
if(t2>'~') t2=' ';
delay(0XFFF);
delay(0XFFF);
} // Spin forever
}串口0采用定时器1来进行产生波特率,定时器1在写入装载值时,由于时钟的问题会产生波特率偏差,在时钟为3062500Hz的情况下,计算写入TH1和TL1的值为13,此时波特率产生实际值为117788,可以看出偏差还是很大,当为9600波特率时,写入TH1和TL1的值为97,此时计算出波特率为9630.偏差比较小。因此在这种情况下我将串口1和串口0的波特率均设置为9600.在测试时要注意,开发板的串口0是通过虚拟串口和其他片外外设进行交互数据,而虚拟串口的波特率是115200,这在手册中有提到,改变不了,因此需要用USB转TTL模块将数据传输到串口助手来查看数据是否对,这个坑坑死人,还不如板载CH340芯片方便。 虚拟串口的介绍如图所示

虚拟串口介绍图
系统的原理图如图所示,原理图首先是电源部分,电源一共包含2部分,一部分是12V转5V部分用来给OLED屏幕,以及串口转485模块供电。还有一部分为5V转3.3V部分用来给MCU供电。然后是MCU部分,MCU部门这里仅引出必要的管脚,TTL转485模块为购置的集成串口转485装置,不用增加485的半双工切换引脚,节省MCU的IO口资源;OLED接口为I2C接口的OLED屏幕,用来显示必要的信息,串口1为引出串口,用来和网关通信,实现数据入云的操作。复位按键用来手动给MCU复位,LED用来作为一些必要的信息指示,调试接口为参考官网原理图的设计的调试接口。系统采用12V供电,

系统原理图
完结撒花,花花花
源码在这里 Terminator.rar 演示视频在这里演示视频
经过几天的奋战,把试用版的功能全部实现了,再絮叨下所完成的内容,用EFM8BB52完成传感器数据的提取。将数据在OLED屏幕上进行显示,然后定时刷新OLED屏幕的数据。为了将数据入网,这里增加了自制网关,网关和EFM8BB52之间采用串口通信,网关数据在接收到数据后,将数据进行处理转换成json字符串,通过http协议上传到服务器。首先EFM8BB52显示结果图如图1所示,服务器端数据网页显示如图2所示(图2后截得图,数据和图1不一样,懒得把收起来的开发板重新开机了)。

图1 OLED采集结果图

图2 服务器网页查看图
现在对系统实物图进行详细介绍,EFM8BB52搭建的系统实物图如图3所示,图3中的电源模块为12转5V电源模块,用来给整个系统包括传感器,开发板,以及网关供电,这里用航空插头作为连接器。由于传感器为485接口,所以增加了TTL转485模块用来和传感器通信。OLED屏幕采用IIC通信的OLED。

图3 系统实物图
网关实物图如图4所示,网关主要负责对接收到的串口数据进行整合处理,处理成json字符串格式,主要是http协议传输的是字符串数据。EFM8BB52为8位MCU处理json转换有点吃力,所以该部分功能放到网关处理,而且EFM8BB52没有网口。数据处理后通过网口和路由器完成入网。监测系统连接实物图如图5所示。

图4 网关实物图

图5 系统连接图
回复
| 有奖活动 | |
|---|---|
| 硬核工程师专属补给计划——填盲盒 | |
| “我踩过的那些坑”主题活动——第002期 | |
| 【EEPW电子工程师创研计划】技术变现通道已开启~ | |
| 发原创文章 【每月瓜分千元赏金 凭实力攒钱买好礼~】 | |
| 【EEPW在线】E起听工程师的声音! | |
| 高校联络员开始招募啦!有惊喜!! | |
| 【工程师专属福利】每天30秒,积分轻松拿!EEPW宠粉打卡计划启动! | |
| 送您一块开发板,2025年“我要开发板活动”又开始了! | |
我要赚赏金打赏帖 |
|
|---|---|
| Chaos-nano:专为低资源单片机设计的轻量级协作式异步操作系统(ATMEGA328P轻量级操作系统)—— 详细介绍被打赏¥16元 | |
| FPGA配置被打赏¥10元 | |
| Chaos-nano协作式异步操作系统:赋能MicrochipAVR8位单片机的革新之路被打赏¥15元 | |
| 基于esp32开发时串口工具的注意点被打赏¥24元 | |
| 基于FireBeetle2ESP32-C5开发板的舵机控制被打赏¥20元 | |
| 【分享开发笔记,赚取电动螺丝刀】MAX78000开发板制作的电子相册被打赏¥32元 | |
| 基于FireBeetle2ESP32-C5开发板的超声波测距及显示被打赏¥21元 | |
| FireBeetle2ESP32-C5上RTC电子时钟的实现被打赏¥25元 | |
| 【分享开发笔记,赚取电动螺丝刀】MAX78000开发板读取SD卡被打赏¥23元 | |
| 【S32K3XX】Standby RAM 重启后数据异常问题调查被打赏¥38元 | |
我要赚赏金
