发 帖  
原厂入驻New

[经验] 【大联大世平ON Semiconductor BLE5.0 RSL10开发板试用体验】项目完结篇:基于RLS10评估板的智能温湿度试验箱控制系统开发

2020-8-29 22:36:27  107
分享
0
       RSL10  为蓝牙低功耗(BLE)系统单芯片(SoC)功能相当强大,集成 双核处理器(ARM® Cortex®-M3处理器、32位Dual-Harvard数字信号处理DSP系统),适用于各种不同传感器的GPIO、LSAD、I2C、SPI、PCM等模拟和数字接口,32位双Harvard核LPDSP32是支持密集型信号处理如音频编解码器的处理器,ARM®Cortex®-M3是用于执行蓝牙低功耗栈和用户应用的处理器,用户可编程,时钟速度达48 MHz,LSAD是用于连接到传感器以形成单芯片系统的A/D转换器。RSL10通过了蓝牙技术联盟(SIG)的蓝牙5认证,包括36个配置文件和服务。
     特点功耗极低,音频解码。下面是SOC架构图。
1.png
     RSL10  芯片和开发板的具体参数,前面已经有介绍。下面重点介绍一下基于RLS10评估板的智能温湿度试验箱控制系统开发。
    介绍下用到的模块:中景园3.5寸TFT LCD 带字库SPI接口320*480 RGB屏,高精度温湿度传感器AM2302,一根线就可以驱动读取数据。

QQ截图20200829215351.jpg
开发板已经把RLS10 PIN都引出来了,评估非常方面。
2.jpg
  本项目是普通口模拟SPI驱动屏。
RLS10 GPIO 操作跟STM32大同小异
            Sys_GPIO_Toggle( SCLK  );  引脚高电平
            Sys_GPIO_Set_Low(SCLK);引脚低电平

宏定义即可移植STM驱动  
#define OLED_SCLK_Clr()   Sys_GPIO_Set_Low(LED_DIO);
#define OLED_SCLK_Set()     Sys_GPIO_Toggle(  SCLK  );  

屏的驱动函数如下:

  1. /******************************************************************************
  2.       函数说明:LCD串行数据写入函数
  3.       入口数据:dat  要写入的串行数据
  4.       返回值:  无
  5. ******************************************************************************/
  6. void LCD_Writ_Bus(u8 dat)
  7. {       
  8.         u8 i;       
  9.   OLED_CS_Clr();       
  10.         for(i=0;i<8;i++)
  11.         {                          
  12.                 OLED_SCLK_Clr();
  13.                 IF(dat&0x80)
  14.                    OLED_SDIN_Set();
  15.                 else
  16.                    OLED_SDIN_Clr();
  17.                 OLED_SCLK_Set();
  18.                 dat<<=1;   
  19.         }
  20.   OLED_CS_Set();       
  21. }


  22. /******************************************************************************
  23.       函数说明:LCD写入数据
  24.       入口数据:dat 写入的数据
  25.       返回值:  无
  26. ******************************************************************************/
  27. void LCD_WR_DATA8(u8 dat)
  28. {
  29.         OLED_DC_Set();//写数据
  30.         LCD_Writ_Bus(dat);
  31. }


  32. /******************************************************************************
  33.       函数说明:LCD写入数据
  34.       入口数据:dat 写入的数据
  35.       返回值:  无
  36. ******************************************************************************/
  37. void LCD_WR_DATA(u16 dat)
  38. {
  39.         OLED_DC_Set();//写数据
  40.         LCD_Writ_Bus(dat>>16);
  41.         LCD_Writ_Bus(dat>>8);
  42.         LCD_Writ_Bus(dat);
  43. }


  44. /******************************************************************************
  45.       函数说明:LCD写入命令
  46.       入口数据:dat 写入的命令
  47.       返回值:  无
  48. ******************************************************************************/
  49. void LCD_WR_REG(u8 dat)
  50. {
  51.         OLED_DC_Clr();//写命令
  52.         LCD_Writ_Bus(dat);
  53. }


  54. /******************************************************************************
  55.       函数说明:设置起始和结束地址
  56.       入口数据:x1,x2 设置列的起始和结束地址
  57.                 y1,y2 设置行的起始和结束地址
  58.       返回值:  无
  59. ******************************************************************************/
  60. void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
  61. {
  62.         LCD_WR_REG(0x2a);//列地址设置
  63.    LCD_WR_DATA8(x1>>8);
  64.    LCD_WR_DATA8(x1);
  65.    LCD_WR_DATA8(x2>>8);
  66.    LCD_WR_DATA8(x2);
  67.    LCD_WR_REG(0x2b);//行地址设置
  68.    LCD_WR_DATA8(y1>>8);
  69.    LCD_WR_DATA8(y1);
  70.    LCD_WR_DATA8(y2>>8);
  71.    LCD_WR_DATA8(y2);
  72.         LCD_WR_REG(0x2c);//储存器写
  73. }


  74. /******************************************************************************
  75.       函数说明:LCD初始化函数
  76.       入口数据:无
  77.       返回值:  无
  78. ******************************************************************************/

  79. //************* Start Initial Sequence **********//
  80. LCD_WR_REG(0x11); //Exit Sleep
  81. delay_ms(60);
  82. LCD_WR_REG(0XF2);
  83. LCD_WR_DATA8(0x18);
  84. LCD_WR_DATA8(0xA3);
  85. LCD_WR_DATA8(0x12);
  86. LCD_WR_DATA8(0x02);
  87. LCD_WR_DATA8(0XB2);
  88. LCD_WR_DATA8(0x12);
  89. LCD_WR_DATA8(0xFF);
  90. LCD_WR_DATA8(0x10);
  91. LCD_WR_DATA8(0x00);
  92. LCD_WR_REG(0XF8);
  93. LCD_WR_DATA8(0x21);
  94. LCD_WR_DATA8(0x04);
  95. LCD_WR_REG(0X13);

  96. LCD_WR_REG(0x36);    // Memory Access Control
  97.         if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x08);
  98.         else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC8);
  99.         else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x78);
  100.         else LCD_WR_DATA8(0xA8);

  101. LCD_WR_REG(0xB4);
  102. LCD_WR_DATA8(0x02);
  103. LCD_WR_REG(0xB6);
  104. LCD_WR_DATA8(0x02);
  105. LCD_WR_DATA8(0x22);
  106. LCD_WR_REG(0xC1);
  107. LCD_WR_DATA8(0x41);
  108. LCD_WR_REG(0xC5);
  109. LCD_WR_DATA8(0x00);
  110. LCD_WR_DATA8(0x18);



  111. LCD_WR_REG(0x3a);
  112. LCD_WR_DATA8(0x66);
  113. delay_ms(50);



  114. LCD_WR_REG(0xE0);
  115. LCD_WR_DATA8(0x0F);
  116. LCD_WR_DATA8(0x1F);
  117. LCD_WR_DATA8(0x1C);
  118. LCD_WR_DATA8(0x0C);
  119. LCD_WR_DATA8(0x0F);
  120. LCD_WR_DATA8(0x08);
  121. LCD_WR_DATA8(0x48);
  122. LCD_WR_DATA8(0x98);
  123. LCD_WR_DATA8(0x37);
  124. LCD_WR_DATA8(0x0A);
  125. LCD_WR_DATA8(0x13);
  126. LCD_WR_DATA8(0x04);
  127. LCD_WR_DATA8(0x11);
  128. LCD_WR_DATA8(0x0D);
  129. LCD_WR_DATA8(0x00);
  130. LCD_WR_REG(0xE1);
  131. LCD_WR_DATA8(0x0F);
  132. LCD_WR_DATA8(0x32);
  133. LCD_WR_DATA8(0x2E);
  134. LCD_WR_DATA8(0x0B);
  135. LCD_WR_DATA8(0x0D);
  136. LCD_WR_DATA8(0x05);
  137. LCD_WR_DATA8(0x47);
  138. LCD_WR_DATA8(0x75);
  139. LCD_WR_DATA8(0x37);
  140. LCD_WR_DATA8(0x06);
  141. LCD_WR_DATA8(0x10);
  142. LCD_WR_DATA8(0x03);
  143. LCD_WR_DATA8(0x24);
  144. LCD_WR_DATA8(0x20);
  145. LCD_WR_DATA8(0x00);
  146. LCD_WR_REG(0x11);
  147. delay_ms(120);
  148. LCD_WR_REG(0x29);
  149. LCD_WR_REG(0x2C);
  150. }


  151. /******************************************************************************
  152.       函数说明:LCD清屏函数
  153.       入口数据:无
  154.       返回值:  无
  155. ******************************************************************************/
  156. void LCD_Clear(u16 Color)
  157. {
  158.         u16 i,j;         
  159.         LCD_Address_Set(0,0,LCD_W-1,LCD_H-1);
  160.     for(i=0;i<LCD_W;i++)
  161.          {
  162.           for (j=0;j<LCD_H;j++)
  163.                    {
  164.                 LCD_WR_DATA(Color);                                  
  165.             }

  166.           }
  167. }


  168. /******************************************************************************
  169.       函数说明:LCD显示汉字
  170.       入口数据:x,y   起始坐标
  171.                 index 汉字的序号
  172.                 size  字号
  173.       返回值:  无
  174. ******************************************************************************/
  175. void LCD_ShowChinese32x32(u16 x,u16 y,u8 index,u8 size,u16 color)       
  176. {  
  177.         u8 i,j;
  178.         u8 *temp,size1;
  179.         if(size==16){temp=Hzk16;}//选择字号
  180.         if(size==32){temp=Hzk32;}
  181.   LCD_Address_Set(x,y,x+size-1,y+size-1); //设置一个汉字的区域
  182.   size1=size*size/8;//一个汉字所占的字节
  183.         temp+=index*size1;//写入的起始位置
  184.         for(j=0;j<size1;j++)
  185.         {
  186.                 for(i=0;i<8;i++)
  187.                 {
  188.                          if((*temp&(1<<i))!=0)//从数据的低位开始读
  189.                         {
  190.                                 LCD_WR_DATA(color);//点亮
  191.                         }
  192.                         else
  193.                         {
  194.                                 LCD_WR_DATA(BACK_COLOR);//不点亮
  195.                         }
  196.                 }
  197.                 temp++;
  198.          }
  199. }


  200. /******************************************************************************
  201.       函数说明:LCD显示汉字
  202.       入口数据:x,y   起始坐标
  203.       返回值:  无
  204. ******************************************************************************/
  205. void LCD_DrawPoint(u16 x,u16 y,u16 color)
  206. {
  207.         LCD_Address_Set(x,y,x,y);//设置光标位置
  208.         LCD_WR_DATA(color);
  209. }


  210. /******************************************************************************
  211.       函数说明:LCD画一个大的点
  212.       入口数据:x,y   起始坐标
  213.       返回值:  无
  214. ******************************************************************************/
  215. void LCD_DrawPoint_big(u16 x,u16 y,u16 color)
  216. {
  217.         LCD_Fill(x-1,y-1,x+1,y+1,color);
  218. }


  219. /******************************************************************************
  220.       函数说明:在指定区域填充颜色
  221.       入口数据:xsta,ysta   起始坐标
  222.                 xend,yend   终止坐标
  223.       返回值:  无
  224. ******************************************************************************/
  225. void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)
  226. {         
  227.         u16 i,j;
  228.         LCD_Address_Set(xsta,ysta,xend,yend);      //设置光标位置
  229.         for(i=ysta;i<=yend;i++)
  230.         {                                                                                                                           
  231.                 for(j=xsta;j<=xend;j++)LCD_WR_DATA(color);//设置光标位置             
  232.         }                                                       
  233. }


  234. /******************************************************************************
  235.       函数说明:画线
  236.       入口数据:x1,y1   起始坐标
  237.                 x2,y2   终止坐标
  238.       返回值:  无
  239. ******************************************************************************/
  240. void LCD_DrawLine(u16 x1,u16 y1,u16 x2,u16 y2,u16 color)
  241. {
  242.         u16 t;
  243.         int xerr=0,yerr=0,delta_x,delta_y,distance;
  244.         int incx,incy,uRow,uCol;
  245.         delta_x=x2-x1; //计算坐标增量
  246.         delta_y=y2-y1;
  247.         uRow=x1;//画线起点坐标
  248.         uCol=y1;
  249.         if(delta_x>0)incx=1; //设置单步方向
  250.         else if (delta_x==0)incx=0;//垂直线
  251.         else {incx=-1;delta_x=-delta_x;}
  252.         if(delta_y>0)incy=1;
  253.         else if (delta_y==0)incy=0;//水平线
  254.         else {incy=-1;delta_y=-delta_x;}
  255.         if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
  256.         else distance=delta_y;
  257.         for(t=0;t<distance+1;t++)
  258.         {
  259.                 LCD_DrawPoint(uRow,uCol,color);//画点
  260.                 xerr+=delta_x;
  261.                 yerr+=delta_y;
  262.                 if(xerr>distance)
  263.                 {
  264.                         xerr-=distance;
  265.                         uRow+=incx;
  266.                 }
  267.                 if(yerr>distance)
  268.                 {
  269.                         yerr-=distance;
  270.                         uCol+=incy;
  271.                 }
  272.         }
  273. }


  274. /******************************************************************************
  275.       函数说明:画矩形
  276.       入口数据:x1,y1   起始坐标
  277.                 x2,y2   终止坐标
  278.       返回值:  无
  279. ******************************************************************************/
  280. void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color)
  281. {
  282.         LCD_DrawLine(x1,y1,x2,y1,color);
  283.         LCD_DrawLine(x1,y1,x1,y2,color);
  284.         LCD_DrawLine(x1,y2,x2,y2,color);
  285.         LCD_DrawLine(x2,y1,x2,y2,color);
  286. }


  287. /******************************************************************************
  288.       函数说明:画圆
  289.       入口数据:x0,y0   圆心坐标
  290.                 r       半径
  291.       返回值:  无
  292. ******************************************************************************/
  293. void Draw_Circle(u16 x0,u16 y0,u8 r,u16 color)
  294. {
  295.         int a,b;
  296.         int di;
  297.         a=0;b=r;          
  298.         while(a<=b)
  299.         {
  300.                 LCD_DrawPoint(x0-b,y0-a,color);             //3           
  301.                 LCD_DrawPoint(x0+b,y0-a,color);             //0           
  302.                 LCD_DrawPoint(x0-a,y0+b,color);             //1               
  303.                 LCD_DrawPoint(x0-a,y0-b,color);             //2            
  304.                 LCD_DrawPoint(x0+b,y0+a,color);             //4               
  305.                 LCD_DrawPoint(x0+a,y0-b,color);             //5
  306.                 LCD_DrawPoint(x0+a,y0+b,color);             //6
  307.                 LCD_DrawPoint(x0-b,y0+a,color);             //7
  308.                 a++;
  309.                 if((a*a+b*b)>(r*r))//判断要画的点是否过远
  310.                 {
  311.                         b--;
  312.                 }
  313.         }
  314. }


  315. /******************************************************************************
  316.       函数说明:显示字符
  317.       入口数据:x,y    起点坐标
  318.                 num    要显示的字符
  319.                 mode   1叠加方式  0非叠加方式
  320.       返回值:  无
  321. ******************************************************************************/
  322. void LCD_ShowChar(u16 x,u16 y,u8 num,u8 mode,u16 color)
  323. {
  324.     u8 temp;
  325.     u8 pos,t;
  326.           u16 x0=x;     
  327.     if(x>LCD_W-16||y>LCD_H-16)return;            //设置窗口                  
  328.         num=num-' ';//得到偏移后的值
  329.         LCD_Address_Set(x,y,x+8-1,y+16-1);      //设置光标位置
  330.         if(!mode) //非叠加方式
  331.         {
  332.                 for(pos=0;pos<16;pos++)
  333.                 {
  334.                         temp=asc2_1608[(u16)num*16+pos];                 //调用1608字体
  335.                         for(t=0;t<8;t++)
  336.                     {                 
  337.                         if(temp&0x01)LCD_WR_DATA(color);
  338.                                     else LCD_WR_DATA(BACK_COLOR);
  339.                                     temp>>=1;
  340.                                     x++;
  341.                     }
  342.                         x=x0;
  343.                         y++;
  344.                 }       
  345.         }else//叠加方式
  346.         {
  347.                 for(pos=0;pos<16;pos++)
  348.                 {
  349.                     temp=asc2_1608[(u16)num*16+pos];                 //调用1608字体
  350.                         for(t=0;t<8;t++)
  351.                     {                 
  352.                         if(temp&0x01)LCD_DrawPoint(x+t,y+pos,color);//画一个点     
  353.                         temp>>=1;
  354.                     }
  355.                 }
  356.         }                                 
  357. }


  358. /******************************************************************************
  359.       函数说明:显示字符串
  360.       入口数据:x,y    起点坐标
  361.                 *p     字符串起始地址
  362.       返回值:  无
  363. ******************************************************************************/
  364. void LCD_ShowString(u16 x,u16 y,const u8 *p,u16 color)
  365. {         
  366.     while(*p!='\0')
  367.     {      
  368.         if(x>LCD_W-16){x=0;y+=16;}
  369.         if(y>LCD_H-16){y=x=0;LCD_Clear(RED);}
  370.         LCD_ShowChar(x,y,*p,0,color);
  371.         x+=8;
  372.         p++;
  373.     }  
  374. }


  375. /******************************************************************************
  376.       函数说明:显示数字
  377.       入口数据:m底数,n指数
  378.       返回值:  无
  379. ******************************************************************************/
  380. u32 mypow(u8 m,u8 n)
  381. {
  382.         u32 result=1;         
  383.         while(n--)result*=m;   
  384.         return result;
  385. }


  386. /******************************************************************************
  387.       函数说明:显示数字
  388.       入口数据:x,y    起点坐标
  389.                 num    要显示的数字
  390.                 len    要显示的数字个数
  391.       返回值:  无
  392. ******************************************************************************/
  393. void LCD_ShowNum(u16 x,u16 y,u16 num,u8 len,u16 color)
  394. {                
  395.         u8 t,temp;
  396.         u8 enshow=0;
  397.         for(t=0;t<len;t++)
  398.         {
  399.                 temp=(num/mypow(10,len-t-1))%10;
  400.                 if(enshow==0&&t<(len-1))
  401.                 {
  402.                         if(temp==0)
  403.                         {
  404.                                 LCD_ShowChar(x+8*t,y,' ',0,color);
  405.                                 continue;
  406.                         }else enshow=1;
  407.                           
  408.                 }
  409.                  LCD_ShowChar(x+8*t,y,temp+48,0,color);
  410.         }
  411. }


  412. /******************************************************************************
  413.       函数说明:显示小数
  414.       入口数据:x,y    起点坐标
  415.                 num    要显示的小数
  416.                 len    要显示的数字个数
  417.       返回值:  无
  418. ******************************************************************************/
  419. void LCD_ShowNum1(u16 x,u16 y,float num,u8 len,u16 color)
  420. {                
  421.         u8 t,temp;
  422.         u8 enshow=0;
  423.         u16 num1;
  424.         num1=num*100;
  425.         for(t=0;t<len;t++)
  426.         {
  427.                 temp=(num1/mypow(10,len-t-1))%10;
  428.                 if(t==(len-2))
  429.                 {
  430.                         LCD_ShowChar(x+8*(len-2),y,'.',0,color);
  431.                         t++;
  432.                         len+=1;
  433.                 }
  434.                  LCD_ShowChar(x+8*t,y,temp+48,0,color);
  435.         }
  436. }


  437. /******************************************************************************
  438.       函数说明:显示40x40图片
  439.       入口数据:x,y    起点坐标
  440.       返回值:  无
  441. ******************************************************************************/
  442. void LCD_ShowPicture(u16 x1,u16 y1,u16 x2,u16 y2)
  443. {
  444.         int i;
  445.           LCD_Address_Set(x1,y1,x2,y2);
  446.                 for(i=0;i<1600;i++)
  447.           {        
  448.                         LCD_WR_DATA8(image[i*3+2]);
  449.                         LCD_WR_DATA8(image[i*3+1]);
  450.                         LCD_WR_DATA8(image[i*3]);               
  451.           }                       
  452. }


复制代码

   传感器时序操作类似dht22
显示效果如下:

微信图片_20200829222306.jpg
动态小时效果如下:
d63aa21db67e996a6b279bc08bcfabea.gif

本项目的难点是把才采集到的温度湿度数据通过RSL10自带的蓝牙服务,实时传送的手机端。关键代码如下:
  1. APP_SetAdvScanData();

  2.     /* Configure Battery Service Server */
  3.     BASS_Initialize(APP_BAS_NB, APP_BASS_ReadBatteryLevel);
  4.     BASS_NotifyOnBattLevelChange(TIMER_SETTING_S(1));     /* Periodically monitor the battery level. Only notify changes */
  5.     BASS_NotifyOnTimeout(TIMER_SETTING_S(6));             /* Periodically notify the battery level to connected peers */
  6.     APP_BASS_SetBatMonAlarm(BATMON_SUPPLY_THRESHOLD_CFG); /* BATMON alarm configuration */

  7.     /* Configure Custom Service Server */
  8.     CUSTOMSS_Initialize();
  9.     CUSTOMSS_NotifyOnTimeout(TIMER_SETTING_S(6)); /* Notify client and fire CUSTOMSS_NTF_TIMEOUT periodically */

  10.     /* Add application message handlers */
  11.     MsgHandler_Add(TASK_ID_GAPM, APP_GAPM_GATTM_Handler);
  12.     MsgHandler_Add(GATTM_ADD_SVC_RSP, APP_GAPM_GATTM_Handler);
  13.     MsgHandler_Add(TASK_ID_GAPC, APP_GAPC_Handler);
  14.     MsgHandler_Add(APP_LED_TIMEOUT, APP_LED_Timeout_Handler);
  15.     MsgHandler_Add(APP_BATT_LEVEL_LOW, APP_BASS_BattLevelLow_Handler);
复制代码


因此特意开发了一款简单的接收蓝牙数据APP。APP效果如下,与显示屏数据吻合。
微信图片_20200829222901.jpg

    有了本套系统,就可以远程实时通过手机读取试验箱的环境参数,还可以实时遥控设定目标参数。便于数据统计你整理归纳。应用十分广泛。





马猛 2020-8-29 22:41:12
本项目由于商业应用中,有限开源,如果对本项目感兴趣的朋友欢迎私信,
1 回复

举报

只有小组成员才能发言,加入小组>>

83个成员聚集在这个小组

加入小组

创建小组步骤

关闭

站长推荐 上一条 /7 下一条

快速回复 返回顶部 返回列表