这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【EFM8BB52单片机】室内环境监测物联网系统(完结)

共35条 2/4 1 2 3 4 跳转至
专家
2021-12-27 10:20:55     打赏
11楼

学习 学习


助工
2021-12-27 10:21:01     打赏
12楼
串口和OLED结合

       因为后面需要用到OLED屏幕显示,这里就开始了整合之路,没有新东西。就像变形金刚里的大力神一样进行组合变形。只是这里遇到一个问题,还是搞不明白,在程序烧录进去后功能没问题。重新上电后需要重启才开始运行。很费解。工程文件在这里 UART_OLED.rar 


助工
2022-01-02 22:38:17     打赏
13楼

串口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口图


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


助工
2022-01-02 22:55:48     打赏
14楼
修改OLED屏幕到这里

     

因为系统需要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
}



助工
2022-01-04 14:52:54     打赏
15楼
串口调试加更

     串口0采用定时器1来进行产生波特率,定时器1在写入装载值时,由于时钟的问题会产生波特率偏差,在时钟为3062500Hz的情况下,计算写入TH1和TL1的值为13,此时波特率产生实际值为117788,可以看出偏差还是很大,当为9600波特率时,写入TH1和TL1的值为97,此时计算出波特率为9630.偏差比较小。因此在这种情况下我将串口1和串口0的波特率均设置为9600.在测试时要注意,开发板的串口0是通过虚拟串口和其他片外外设进行交互数据,而虚拟串口的波特率是115200,这在手册中有提到,改变不了,因此需要用USB转TTL模块将数据传输到串口助手来查看数据是否对,这个坑坑死人,还不如板载CH340芯片方便。 虚拟串口的介绍如图所示

1641279086693261.png

  虚拟串口介绍图



高工
2022-01-04 15:03:36     打赏
16楼

学习一下 谢谢


助工
2022-01-04 16:16:24     打赏
17楼
系统原理图详解

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

1641284120986020.png

系统原理图



高工
2022-01-04 16:34:32     打赏
18楼

系统做的还是蛮不错的,学习学习


助工
2022-01-05 20:21:55     打赏
19楼

完结撒花,花花花

     源码在这里 Terminator.rar  演示视频在这里演示视频

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

OLED显示图

1 OLED采集结果图

22.png

2 服务器网页查看图

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

3.png

3 系统实物图

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

4.jpg

4 网关实物图

   

5.png

5 系统连接图

 

 

 

 

 



高工
2022-01-05 22:06:32     打赏
20楼

谢谢


共35条 2/4 1 2 3 4 跳转至

回复

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