` 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架构图。
RSL10 芯片和 开发板的具体参数,前面已经有介绍。下面重点介绍一下基于RLS10评估板的智能温湿度试验箱控制系统开发。
介绍下用到的模块:中景园3.5寸TFT LCD 带字库SPI接口320*480 RGB屏,高精度温湿度传感器AM2302,一根线就可以驱动读取数据。
开发板已经把RLS10 PIN都引出来了,评估非常方面。
本项目是普通口模拟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 );
屏的驱动函数如下:
- /******************************************************************************
- 函数说明:LCD串行数据写入函数
- 入口数据:dat 要写入的串行数据
- 返回值: 无
- ******************************************************************************/
- void LCD_Writ_Bus(u8 dat)
- {
- u8 i;
- OLED_CS_Clr();
- for(i=0;i<8;i++)
- {
- OLED_SCLK_Clr();
- if(dat&0x80)
- OLED_SDIN_Set();
- else
- OLED_SDIN_Clr();
- OLED_SCLK_Set();
- dat<<=1;
- }
- OLED_CS_Set();
- }
- /******************************************************************************
- 函数说明:LCD写入数据
- 入口数据:dat 写入的数据
- 返回值: 无
- ******************************************************************************/
- void LCD_WR_DATA8(u8 dat)
- {
- OLED_DC_Set();//写数据
- LCD_Writ_Bus(dat);
- }
- /******************************************************************************
- 函数说明:LCD写入数据
- 入口数据:dat 写入的数据
- 返回值: 无
- ******************************************************************************/
- void LCD_WR_DATA(u16 dat)
- {
- OLED_DC_Set();//写数据
- LCD_Writ_Bus(dat>>16);
- LCD_Writ_Bus(dat>>8);
- LCD_Writ_Bus(dat);
- }
- /******************************************************************************
- 函数说明:LCD写入命令
- 入口数据:dat 写入的命令
- 返回值: 无
- ******************************************************************************/
- void LCD_WR_REG(u8 dat)
- {
- OLED_DC_Clr();//写命令
- LCD_Writ_Bus(dat);
- }
- /******************************************************************************
- 函数说明:设置起始和结束地址
- 入口数据:x1,x2 设置列的起始和结束地址
- y1,y2 设置行的起始和结束地址
- 返回值: 无
- ******************************************************************************/
- void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
- {
- LCD_WR_REG(0x2a);//列地址设置
- LCD_WR_DATA8(x1>>8);
- LCD_WR_DATA8(x1);
- LCD_WR_DATA8(x2>>8);
- LCD_WR_DATA8(x2);
- LCD_WR_REG(0x2b);//行地址设置
- LCD_WR_DATA8(y1>>8);
- LCD_WR_DATA8(y1);
- LCD_WR_DATA8(y2>>8);
- LCD_WR_DATA8(y2);
- LCD_WR_REG(0x2c);//储存器写
- }
- /******************************************************************************
- 函数说明:LCD初始化函数
- 入口数据:无
- 返回值: 无
- ******************************************************************************/
- //************* Start Initial Sequence **********//
- LCD_WR_REG(0x11); //Exit Sleep
- delay_ms(60);
- LCD_WR_REG(0XF2);
- LCD_WR_DATA8(0x18);
- LCD_WR_DATA8(0xA3);
- LCD_WR_DATA8(0x12);
- LCD_WR_DATA8(0x02);
- LCD_WR_DATA8(0XB2);
- LCD_WR_DATA8(0x12);
- LCD_WR_DATA8(0xFF);
- LCD_WR_DATA8(0x10);
- LCD_WR_DATA8(0x00);
- LCD_WR_REG(0XF8);
- LCD_WR_DATA8(0x21);
- LCD_WR_DATA8(0x04);
- LCD_WR_REG(0X13);
- LCD_WR_REG(0x36); // Memory Access Control
- if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x08);
- else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC8);
- else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x78);
- else LCD_WR_DATA8(0xA8);
- LCD_WR_REG(0xB4);
- LCD_WR_DATA8(0x02);
- LCD_WR_REG(0xB6);
- LCD_WR_DATA8(0x02);
- LCD_WR_DATA8(0x22);
- LCD_WR_REG(0xC1);
- LCD_WR_DATA8(0x41);
- LCD_WR_REG(0xC5);
- LCD_WR_DATA8(0x00);
- LCD_WR_DATA8(0x18);
- LCD_WR_REG(0x3a);
- LCD_WR_DATA8(0x66);
- delay_ms(50);
- LCD_WR_REG(0xE0);
- LCD_WR_DATA8(0x0F);
- LCD_WR_DATA8(0x1F);
- LCD_WR_DATA8(0x1C);
- LCD_WR_DATA8(0x0C);
- LCD_WR_DATA8(0x0F);
- LCD_WR_DATA8(0x08);
- LCD_WR_DATA8(0x48);
- LCD_WR_DATA8(0x98);
- LCD_WR_DATA8(0x37);
- LCD_WR_DATA8(0x0A);
- LCD_WR_DATA8(0x13);
- LCD_WR_DATA8(0x04);
- LCD_WR_DATA8(0x11);
- LCD_WR_DATA8(0x0D);
- LCD_WR_DATA8(0x00);
- LCD_WR_REG(0xE1);
- LCD_WR_DATA8(0x0F);
- LCD_WR_DATA8(0x32);
- LCD_WR_DATA8(0x2E);
- LCD_WR_DATA8(0x0B);
- LCD_WR_DATA8(0x0D);
- LCD_WR_DATA8(0x05);
- LCD_WR_DATA8(0x47);
- LCD_WR_DATA8(0x75);
- LCD_WR_DATA8(0x37);
- LCD_WR_DATA8(0x06);
- LCD_WR_DATA8(0x10);
- LCD_WR_DATA8(0x03);
- LCD_WR_DATA8(0x24);
- LCD_WR_DATA8(0x20);
- LCD_WR_DATA8(0x00);
- LCD_WR_REG(0x11);
- delay_ms(120);
- LCD_WR_REG(0x29);
- LCD_WR_REG(0x2C);
- }
- /******************************************************************************
- 函数说明:LCD清屏函数
- 入口数据:无
- 返回值: 无
- ******************************************************************************/
- void LCD_Clear(u16 Color)
- {
- u16 i,j;
- LCD_Address_Set(0,0,LCD_W-1,LCD_H-1);
- for(i=0;i
- {
- for (j=0;j
- {
- LCD_WR_DATA(Color);
- }
- }
- }
- /******************************************************************************
- 函数说明:LCD显示汉字
- 入口数据:x,y 起始坐标
- index 汉字的序号
- size 字号
- 返回值: 无
- ******************************************************************************/
- void LCD_ShowChinese32x32(u16 x,u16 y,u8 index,u8 size,u16 color)
- {
- u8 i,j;
- u8 *temp,size1;
- if(size==16){temp=Hzk16;}//选择字号
- if(size==32){temp=Hzk32;}
- LCD_Address_Set(x,y,x+size-1,y+size-1); //设置一个汉字的区域
- size1=size*size/8;//一个汉字所占的字节
- temp+=index*size1;//写入的起始位置
- for(j=0;j
- {
- for(i=0;i<8;i++)
- {
- if((*temp&(1<
- {
- LCD_WR_DATA(color);//点亮
- }
- else
- {
- LCD_WR_DATA(BACK_COLOR);//不点亮
- }
- }
- temp++;
- }
- }
- /******************************************************************************
- 函数说明:LCD显示汉字
- 入口数据:x,y 起始坐标
- 返回值: 无
- ******************************************************************************/
- void LCD_DrawPoint(u16 x,u16 y,u16 color)
- {
- LCD_Address_Set(x,y,x,y);//设置光标位置
- LCD_WR_DATA(color);
- }
- /******************************************************************************
- 函数说明:LCD画一个大的点
- 入口数据:x,y 起始坐标
- 返回值: 无
- ******************************************************************************/
- void LCD_DrawPoint_big(u16 x,u16 y,u16 color)
- {
- LCD_Fill(x-1,y-1,x+1,y+1,color);
- }
- /******************************************************************************
- 函数说明:在指定区域填充颜色
- 入口数据:xsta,ysta 起始坐标
- xend,yend 终止坐标
- 返回值: 无
- ******************************************************************************/
- void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)
- {
- u16 i,j;
- LCD_Address_Set(xsta,ysta,xend,yend); //设置光标位置
- for(i=ysta;i<=yend;i++)
- {
- for(j=xsta;j<=xend;j++)LCD_WR_DATA(color);//设置光标位置
- }
- }
- /******************************************************************************
- 函数说明:画线
- 入口数据:x1,y1 起始坐标
- x2,y2 终止坐标
- 返回值: 无
- ******************************************************************************/
- void LCD_DrawLine(u16 x1,u16 y1,u16 x2,u16 y2,u16 color)
- {
- u16 t;
- int xerr=0,yerr=0,delta_x,delta_y,distance;
- int incx,incy,uRow,uCol;
- delta_x=x2-x1; //计算坐标增量
- delta_y=y2-y1;
- uRow=x1;//画线起点坐标
- uCol=y1;
- if(delta_x>0)incx=1; //设置单步方向
- else if (delta_x==0)incx=0;//垂直线
- else {incx=-1;delta_x=-delta_x;}
- if(delta_y>0)incy=1;
- else if (delta_y==0)incy=0;//水平线
- else {incy=-1;delta_y=-delta_x;}
- if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
- else distance=delta_y;
- for(t=0;t
- {
- LCD_DrawPoint(uRow,uCol,color);//画点
- xerr+=delta_x;
- yerr+=delta_y;
- if(xerr>distance)
- {
- xerr-=distance;
- uRow+=incx;
- }
- if(yerr>distance)
- {
- yerr-=distance;
- uCol+=incy;
- }
- }
- }
- /******************************************************************************
- 函数说明:画矩形
- 入口数据:x1,y1 起始坐标
- x2,y2 终止坐标
- 返回值: 无
- ******************************************************************************/
- void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color)
- {
- LCD_DrawLine(x1,y1,x2,y1,color);
- LCD_DrawLine(x1,y1,x1,y2,color);
- LCD_DrawLine(x1,y2,x2,y2,color);
- LCD_DrawLine(x2,y1,x2,y2,color);
- }
- /******************************************************************************
- 函数说明:画圆
- 入口数据:x0,y0 圆心坐标
- r 半径
- 返回值: 无
- ******************************************************************************/
- void Draw_Circle(u16 x0,u16 y0,u8 r,u16 color)
- {
- int a,b;
- int di;
- a=0;b=r;
- while(a<=b)
- {
- LCD_DrawPoint(x0-b,y0-a,color); //3
- LCD_DrawPoint(x0+b,y0-a,color); //0
- LCD_DrawPoint(x0-a,y0+b,color); //1
- LCD_DrawPoint(x0-a,y0-b,color); //2
- LCD_DrawPoint(x0+b,y0+a,color); //4
- LCD_DrawPoint(x0+a,y0-b,color); //5
- LCD_DrawPoint(x0+a,y0+b,color); //6
- LCD_DrawPoint(x0-b,y0+a,color); //7
- a++;
- if((a*a+b*b)>(r*r))//判断要画的点是否过远
- {
- b--;
- }
- }
- }
- /******************************************************************************
- 函数说明:显示字符
- 入口数据:x,y 起点坐标
- num 要显示的字符
- mode 1叠加方式 0非叠加方式
- 返回值: 无
- ******************************************************************************/
- void LCD_ShowChar(u16 x,u16 y,u8 num,u8 mode,u16 color)
- {
- u8 temp;
- u8 pos,t;
- u16 x0=x;
- if(x>LCD_W-16||y>LCD_H-16)return; //设置窗口
- num=num-' ';//得到偏移后的值
- LCD_Address_Set(x,y,x+8-1,y+16-1); //设置光标位置
- if(!mode) //非叠加方式
- {
- for(pos=0;pos<16;pos++)
- {
- temp=asc2_1608[(u16)num*16+pos]; //调用1608字体
- for(t=0;t<8;t++)
- {
- if(temp&0x01)LCD_WR_DATA(color);
- else LCD_WR_DATA(BACK_COLOR);
- temp>>=1;
- x++;
- }
- x=x0;
- y++;
- }
- }else//叠加方式
- {
- for(pos=0;pos<16;pos++)
- {
- temp=asc2_1608[(u16)num*16+pos]; //调用1608字体
- for(t=0;t<8;t++)
- {
- if(temp&0x01)LCD_DrawPoint(x+t,y+pos,color);//画一个点
- temp>>=1;
- }
- }
- }
- }
- /******************************************************************************
- 函数说明:显示字符串
- 入口数据:x,y 起点坐标
- *p 字符串起始地址
- 返回值: 无
- ******************************************************************************/
- void LCD_ShowString(u16 x,u16 y,const u8 *p,u16 color)
- {
- while(*p!='\0')
- {
- if(x>LCD_W-16){x=0;y+=16;}
- if(y>LCD_H-16){y=x=0;LCD_Clear(RED);}
- LCD_ShowChar(x,y,*p,0,color);
- x+=8;
- p++;
- }
- }
- /******************************************************************************
- 函数说明:显示数字
- 入口数据:m底数,n指数
- 返回值: 无
- ******************************************************************************/
- u32 mypow(u8 m,u8 n)
- {
- u32 result=1;
- while(n--)result*=m;
- return result;
- }
- /******************************************************************************
- 函数说明:显示数字
- 入口数据:x,y 起点坐标
- num 要显示的数字
- len 要显示的数字个数
- 返回值: 无
- ******************************************************************************/
- void LCD_ShowNum(u16 x,u16 y,u16 num,u8 len,u16 color)
- {
- u8 t,temp;
- u8 enshow=0;
- for(t=0;t
- {
- temp=(num/mypow(10,len-t-1))%10;
- if(enshow==0&&t<(len-1))
- {
- if(temp==0)
- {
- LCD_ShowChar(x+8*t,y,' ',0,color);
- continue;
- }else enshow=1;
-
- }
- LCD_ShowChar(x+8*t,y,temp+48,0,color);
- }
- }
- /******************************************************************************
- 函数说明:显示小数
- 入口数据:x,y 起点坐标
- num 要显示的小数
- len 要显示的数字个数
- 返回值: 无
- ******************************************************************************/
- void LCD_ShowNum1(u16 x,u16 y,float num,u8 len,u16 color)
- {
- u8 t,temp;
- u8 enshow=0;
- u16 num1;
- num1=num*100;
- for(t=0;t
- {
- temp=(num1/mypow(10,len-t-1))%10;
- if(t==(len-2))
- {
- LCD_ShowChar(x+8*(len-2),y,'.',0,color);
- t++;
- len+=1;
- }
- LCD_ShowChar(x+8*t,y,temp+48,0,color);
- }
- }
- /******************************************************************************
- 函数说明:显示40x40图片
- 入口数据:x,y 起点坐标
- 返回值: 无
- ******************************************************************************/
- void LCD_ShowPicture(u16 x1,u16 y1,u16 x2,u16 y2)
- {
- int i;
- LCD_Address_Set(x1,y1,x2,y2);
- for(i=0;i<1600;i++)
- {
- LCD_WR_DATA8(image[i*3+2]);
- LCD_WR_DATA8(image[i*3+1]);
- LCD_WR_DATA8(image[i*3]);
- }
- }
复制代码
传感器时序操作类似DHT22。
显示效果如下:
动态小时效果如下:
本项目的难点是把才采集到的温度湿度数据通过RSL10自带的蓝牙服务,实时传送的 手机端。关键代码如下:
- APP_SetAdvScanData();
- /* Configure Battery Service Server */
- BASS_Initialize(APP_BAS_NB, APP_BASS_ReadBatteryLevel);
- BASS_NotifyOnBattLevelChange(TIMER_SETTING_S(1)); /* Periodically monitor the battery level. Only notify changes */
- BASS_NotifyOnTimeout(TIMER_SETTING_S(6)); /* Periodically notify the battery level to connected peers */
- APP_BASS_SetBatMonAlarm(BATMON_SUPPLY_THRESHOLD_CFG); /* BATMON alarm configuration */
- /* Configure Custom Service Server */
- CUSTOMSS_Initialize();
- CUSTOMSS_NotifyOnTimeout(TIMER_SETTING_S(6)); /* Notify client and fire CUSTOMSS_NTF_TIMEOUT periodically */
- /* Add application message handlers */
- MsgHandler_Add(TASK_ID_GAPM, APP_GAPM_GATTM_Handler);
- MsgHandler_Add(GATTM_ADD_SVC_RSP, APP_GAPM_GATTM_Handler);
- MsgHandler_Add(TASK_ID_GAPC, APP_GAPC_Handler);
- MsgHandler_Add(APP_LED_TIMEOUT, APP_LED_Timeout_Handler);
- MsgHandler_Add(APP_BATT_LEVEL_LOW, APP_BASS_BattLevelLow_Handler);
复制代码
因此特意开发了一款简单的接收蓝牙数据APP。APP效果如下,与显示屏数据吻合。
有了本套系统,就可以远程实时通过手机读取试验箱的环境参数,还可以实时遥控设定目标参数。便于数据统计你整理归纳。应用十分广泛。
`
|