nRF51822蓝牙学习 进程记录 3:蓝牙协议学习--简单使用
三天打鱼两天晒网,又学起了蓝牙,不过还好的是终于开始学习蓝牙协议部分了。
但是,一看起来增加了蓝牙协议的例程,真是没头绪啊。本身的教程资料解说太差了,看青风的蓝牙原理详解也是一头雾水。
经过不断地看各种资料,终于决定,不管他了,先学会例程修改再说。
例程里面有个 蓝牙综合例程,就它了。
使用的是LP电子的手环学习开发板。按照教程下载了协议,然后下载了编译文件,最后手机上安装了对应的LP的安卓软件。很好,启动成功,可以点灯,但是温度和授时按钮没用。而且这个例程和其他基于蓝牙协议的例程没有一个带OLED显示的例子。还想以后能手机控制开发板来操控OLED显示呢,怎么办,只有自己一步一步试试了。
先到这个例程的main函数中看看。
1 int main(void)
2 {
3 uint32_t err_code;
4 uint8_t start_string[] = START_STRING;
5 led_init();
6 DS18B20_Init();
7 // Initialize.
8 APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);//时钟初始化
9 usart_init(); //串口初始化
10 ble_stack_init(); //协议初始化
11 gap_params_init(); //参数设置
12 services_init(); //通信服务
13 advertising_init(); //广播设置
14 conn_params_init(); //连接参数
15
16 printf("%s\r\n",start_string);
17
18 err_code = ble_advertising_start(BLE_ADV_MODE_FAST); //¿ªÊ¼¹ã²¥
19 APP_ERROR_CHECK(err_code);
20
21 // Enter main loop.
22 for (;;)
23 {
24 power_manage();
25 }
26 }
额........没发现有啥基础性的东西.......
再找找吧。往上转了转,哎,发现个东西。
1 static void nus_data_handler(ble_nus_t * p_nus, uint8_t * p_data, uint16_t length)//蓝牙接收
2 {
3 printf("p_data=%s\r\n",p_data);
4 uint32_t err_code;
5 short temp=0;
6 uint8_t data[3];
7 switch(p_data[0])
8 {
9 case 0x31:
10 nrf_gpio_pin_toggle(8); //控制LED
11 break;
12 case 0x32: //
13 nrf_gpio_pin_toggle(9);
14 break;
15 case 0x34: //
16 nrf_gpio_pin_toggle(10);
17 break;
18 case 0x33: // 温度接收
19 temp=DS18B20_Get_Temp();
20 data[0]=temp/100+0x30;
21 data[1]=temp/10%10+0x30;
22 data[2]=temp%10+0x30;
23 err_code = ble_nus_string_send(&m_nus, data, 3);
24 if (err_code != NRF_ERROR_INVALID_STATE)
25 {
26 APP_ERROR_CHECK(err_code);
27 }
28 break;
29
30 }
31 }
这个不就是我要找的!!虽然咱还不明白蓝牙协议到底怎么用的,但是用人家写好的还是可以的。
有了人家按钮接收对应的协议,那拿来直接用就完了。
上面的第三行有个串口输出,输出的是p_data,这个是干什么使的?试一试吧。
插上串口线,打开串口调试助手,发现按一个按钮显示一个数,转换为16进制正好和 case 后的数一样。这不就是输出按钮协议的吗。很好。可是很快又发现,在switch 中,p_data 是个数组!看样只是个一维数组,那这个数组到底都包括啥?都是干啥使得?仿照上面的printf 在后面加几行,将整个数组全输出,将原来的字符串输出%s换为数据输出%d,如下:
1 //用于电脑串口输出查看p_data
2 printf("p_data[0]=%d\r\n",p_data[0]);
3 printf("p_data[1]=%d\r\n",p_data[1]);
4 printf("p_data[2]=%d\r\n",p_data[2]);
5 printf("p_data[3]=%d\r\n",p_data[3]);
6 printf("p_data[4]=%d\r\n",p_data[4]);
7 printf("p_data[5]=%d\r\n",p_data[5]);
8 printf("p_data[6]=%d\r\n",p_data[6]);
得到类似数据:(这个是点击授时按钮获得的)
p_data[0]=53
p_data[1]=168
p_data[2]=250
p_data[3]=170
p_data[4]=88
p_data[5]=0
p_data[6]=0
多按几个按钮对比可得:p_data[0]为按钮对应的协议数据,p_data[1]、p_data[2]、p_data[3]与相应的按钮有关,p_data[4]都是88.
好了,手机上的几个按钮对应的数据弄清楚了,那就将上面几个按钮没实现的功能加上去吧。比如 授时 和温度显示 按钮都没用,而 亮度显示 按钮因为开发板上没有光敏电阻,就没管它。
首先,它的读取温度函数不知哪儿有毛病,也没工夫再找一遍了,直接删除,将我自己的ds18b20的函数移植进去。好了,串口和手机显示温度正常。可以发现, ble_nus_string_send(&m_nus, data, 3)这个函数是蓝牙的数据发送函数,很有用,只是目前还不会用,先标记着。(目前的目标是先会移植使用人家的)。
再加入OLED显示函数吧。照着之前的移植方法将周立功的ZLG_GUI再移植上。简单写一个初始化函数并加入main()函数中,放在 协议初始化 之前。然后将OLED显示温度函数showtemp(x,y) 加在读取温度的 case 0x33: 后面,并加上缓存显示函数GUI_Exec();运行可以发现只有点击了 温度 按钮,屏幕才会更新数据,因为看main()函数可以发现,无限运行的 for (;;) 中只有一个低电量运行的函数(24行),此时的case 猜测是利用中断来运行得,所以只有触发了case 才会运行里面的函数。
这样感觉很low(我先加上了时间显示函数,连同时间都是需要点一下按钮才更新一下屏幕,没意思),所以加上以前的中断刷屏函数试试。添加time.c,将定时器的启动初始化加到main()函数中,删去放在showtemp(x,y)后面的GUI_Exec(),运行发现可以显示。但由于温度读取还是和case挂钩,所以还是只有点了温度 按钮温度才会更新变化。(解决方法和时间函数更新一样,马上就说到)。
加入时钟函数。按照之前编写的 万年历,添加相应的rtc文件。 本来的历程中就包含时间函数,经读取p_data 数组可以发现,按下 授时 按钮获取的p_data[1]、p_data[2]、p_data[3]就是时间数。我还简单仿写了时间转换函数,将时间转换为带年月日的结构体:
1 int time_thansform(datetime *time_now,uint8_t *now)
2 {
3
4 uint32_t temp=0,temp_now = 0;
5 uint16_t temp1 = 0;
6 uint8_t a,b,c;
7
8
9 a=now[1];
10 b=now[2];
11 c=now[3];
12 temp_now=(c<<6)+(b<<3)+a;
13 temp = temp_now / 86400; //得到天数
14 {
15 temp1 = 1970; //从1970年开始
16 while(temp >= 365)
17 {
18 if(Is_Leap_Year(temp1))//是闰年
19 {
20 if(temp >= 366)
21 temp -= 366; //闰年的秒钟数
22 else
23 {
24 temp1++;
25 break;
26 }
27 }
28 else
29 temp -= 365; //平年
30 temp1++;
31 }
32 time_now->year = temp1; //得到年份
33 temp1 = 0;
34 while(temp >= 28)
35 {
36 if(Is_Leap_Year(time_now->year) && temp1 == 1) //若是闰年
37 {
38 if(temp >= 29)temp -= 29; //闰年的秒钟数
39 else break;
40 }
41 else
42 {
43 if(temp >= mon_table[temp1])temp -= mon_table[temp1]; //平年
44 else break;
45 }
46 temp1++;
47 }
48 time_now->month = temp1 + 1; //得到月份
49 time_now->day = temp + 1; //日期
50 }
51 temp = temp_now % 86400; //秒钟数
52 time_now->h = temp / 3600; //小时
53 time_now->m = (temp % 3600) / 60; //分钟
54 time_now->s = (temp % 3600) % 60; //秒钟
55 time_now->week = rtc_get_week(time_now->year, time_now->month, time_now->day); //»ñÈ¡ÐÇÆÚ
56 return 0;
57
58 }
不过看了半天还是没明白怎么设置它的时钟。索性将main中的时钟初始化函数删去,加上我之前学习外设时用的时钟初始化函数和时间设置函数(见源文件中的MY_Init()函数),并在timer.c的中断函数中的屏幕刷新函数之前添加之前编写的时间显示函数 showtime(x,y),也可以替换为编写好的模拟时钟函数,当然,还可以利用手机的按钮函数来进行模拟时钟和数字时钟的切换,稍微加点函数就好 ,此处只用数字时钟。在switch 中添加 授时 按钮对应的操作:
1 case 0x35: //按钮 授时 对应的协议,由上面的printf测得
2 rtc_date_get(time_now1); //自己的时钟对应的时间函数
3 //ble_time_set(time_now1,p_data);//本行可以得出只修改p_data的数据是无法修改例子中的计时器的底层函数的
4 time_thansform(time_now1,p_data);
5 printf("year:%d\r\n",time_now1->year);
6 printf("month:%d\r\n",time_now1->month);
7 printf("day:%d\r\n",time_now1->day);
8 //printf("weak:%d\r\n",time_now1->week);
9 printf("h:%d\r\n",time_now1->h);
10 printf("m:%d\r\n",time_now1->m);
11 printf("s:%d\r\n",time_now1->s);
12
13
14 break;
15
添加好头文件和文件后,编译通过,下载可以看到时间不断更新,按手机的 授时 按钮串口显示时间,按温度 温度也更新。
本文源文件
蓝牙协议的详细功能还有待慢慢发现,现在只是简单地是用别人写好的东西来入门。详细的使用还要慢慢学习。
本文水平有限,内容很多词语由于知识水平问题不严谨或很离谱,但主要作为记录作用,能理解就好了,希望以后的自己和路过的大神对必要的错误提出批评与指点,对可笑的错误不要嘲笑,指出来我会改正的。谢谢。我是执念执战,转载请注明出处,谢谢。-------------随梦,随心,随愿,执念执战,执战苍天!
nRF51822蓝牙学习 进程记录 3:蓝牙协议学习--简单使用的更多相关文章
- 蓝牙(Bluetooth) IEEE 802.15.1 协议学习
catalogue . 蓝牙概念 . 配对和连接 . 机密安全性 . 蓝牙协议分类 . 蓝牙协议栈 1. 蓝牙概念 蓝牙(Bluetooth)是一种无线技术标准,可实现固定设备.移动设备和楼宇个人域网 ...
- nRF51800 蓝牙学习 进程记录 1:感想
一直想开一个高大上点的博客,觉得博客园不错,便申请了.一直没时间看,都快忘了,无意间登上提示申请到了.便写个东西看看. 正在学习nRF51822的蓝牙开发板,为了做毕设准备.备考中,一直没时间学,但今 ...
- nRF51800 蓝牙学习 进程记录 2:关于二维数组 执念执战
前天在玩OLED时想完成一直想弄得一个东西,就是简单的单片机游戏.因为STM32和nRF51822的内存足够,所以就用缓存数组的方法来显示图像(我也不知道术语是啥,反正就是在内存中建立一个128X64 ...
- 学习笔记一:I2C协议学习和Verilog实现
////////////////////////////////////////////////// //clk = 20 MHz ,一个周期50ns //sck = 100 kHz (scl) ,一 ...
- STM32学习进程
新建一个自己的工程模板,以我所用的MDK4为例 MDK4软件图标 (1)新建一个自己储存数据的文件夹.以我自己为例(文件夹名字任取自己记住熟悉就行,以下将以我的文件夹文件进行操作讲解) 新建的总体文件 ...
- 蓝牙 BLE 协议学习: 000-有关概念介绍
背景 在学校内就用过蓝牙技术参加过比赛(并拿了奖):而蓝牙作为物联网中比较常见的协议,有必要进行深入的学习.此后的文章会以 ble(v4.0) 进行学习. 介绍 蓝牙技术最初由电信巨头爱立信公司于 1 ...
- 蓝牙 BLE 协议学习: 3种蓝牙架构实现方案(蓝牙协议栈方案)
导言 不同的蓝牙架构可以用在不同的场景中.从而协议帧的架构方案也会不同. 转载自:<三种蓝牙架构实现方案(蓝牙协议栈方案)> 蓝牙架构实现方案有哪几种?我们一般把整个蓝牙实现方案叫做蓝牙协 ...
- 蓝牙 BLE 协议学习: 001-BLE协议栈整体架构
背景 在深入BLE协议帧之前,我们先看一下BLE协议栈整体架构. 转载自:<深入浅出低功耗蓝牙(BLE)协议栈> 架构 如上图所述,要实现一个BLE应用,首先需要一个支持BLE射频的芯片, ...
- 苹果ANCS协议学习【转】
苹果ANCS协议学习 转自:http://www.cnblogs.com/alexcai/p/4321514.html 综述 苹果通知中心(Apple Notification Center Serv ...
- TCP/IP协议学习之实例ping命令学习笔记
TCP/IP协议学习之实例ping命令学习笔记(一) 一. 目的为了让网络协议学习更有效果,在真实网络上进行ping命令前相关知识的学习,暂时不管DNS,在内网中,进行2台主机间的ping命令的整个详 ...
随机推荐
- 第13周 预习、实验与作业:Java网络编程
编写一个网络程序,为了与其他网络程序通信,至少要知道对方的什么信息? IP地址 TCP与UDP协议有什么不同的呢?什么时候该选择哪种协议?HTTP使用的是TCP还是UDP?不重要的短信息传送之类的功能 ...
- linux命令测试中运行
1.1 scp 命令-拷贝文件 scp local_file remote_username@remote_ip:remote_folder eg : scp G96S.Z.16m root@19 ...
- Python 新环境常见问题
Troubleshooting when run python script in new environment 1. Error: pluggy._manager.PluginValidation ...
- 深入Alertmanager 概念与配置介绍
原文: https://www.cnblogs.com/gered/p/13496950.html 警报一直是整个监控系统中的重要组成部分,Prometheus监控系统中,采集与警报是分离的.警报规则 ...
- JAVA仓库管理系统(附源码+调试)
JAVA仓库管理系统--三只松鼠仓库管理系统功能描述(1)登录模块:登录信息等存储在数据库中(2)基本档案管理模块:供货商管理,销售商管理,货品档案管理,仓库管理(3)采购订货模块:用户可以通过查询条 ...
- WebApi EF Core 2.1 Code First 设置导航属性,外键
Nuget: Microsoft.AspNetCore.All Microsoft.EntityFrameworkCore//Include 导航属性在此空间 Microsoft.EntityFram ...
- 性能测试记录: ZZ 只改5行代码获得10倍吞吐量提升
首先得找台足够性能的机器来测试,性能不足时代码运行会出现各种奇怪的现象,导致浪费时间 文章: https://www.jianshu.com/p/4cd8596352ad 只改了5行代码吞吐量提升 ...
- 学习Anaconda,jupyter notebook
20200210,理解了jupyter在anaconda中的意义,vs code觉得对我这个初学者来讲,更容易使用,pycharm虽然破解安装了,但是感觉不太好用,随后再说 20200211, jup ...
- Python学习:Mysql(三)索引
1.索引 索引是表的目录,在查找内容之前可以先在目录中查找索引位置,以此快速定位查询数据.对于索引,会保存在额外的文件中. 2.索引种类 普通索引:仅加速查询 唯一索引:加速查询 + 列值唯一(可以有 ...
- ASP.NET Core中使用日志组件NLog
上一篇文章描述了如何在ASP.NET Core中使用Log4Net记录日志.本篇将使用另外一个组件NLog在ASP.NET Core中记录日志. 1.引入程序集 NLog.Web.AspNetCore ...