RTL8762C SDK开发-点灯及UART-程序员宅基地

技术标签: 单片机  

前言

 

        单片机的世界从点灯开始。

        RTL8762是BLE蓝牙芯片,SOC,是性能比51单片机高出很多的存在,甚至不弱于一些ARM32位单片机,不用来点灯真是太可惜。

        关于蓝牙开始很多人都有误解,认为蓝牙就是可以连接电脑,播放歌曲。那是传统蓝牙给人们的印象太深刻了。蓝牙3.0以下版本都是传统蓝牙,追求的是HIFI,可以连续播放歌曲,而不用考虑功率。

        蓝牙4.0版本(BLE蓝牙低功耗)以上是用来传少量的数据控制指令,而不是传歌曲这种流量大户,4.0、5.0不是3.0传统蓝牙的替代,是共存的。并且4.0、5.0在低功耗领域为蓝牙技术开辟了新的战场,以适应物联网时代的到来。物联网时代要时时在线,低功耗是必须的选择。

        BLE可以干什么?

        点灯---蓝牙点灯,或者叫无线点灯

        RTL8762的世界也是从点灯开始。

一、开始

        本文所用源码基于BEE2-SDK-v1.2.0修改而来,BEE2-SDK-v1.2.0是RTL8762的SDK,官方管RTL8762系列叫小蜜蜂(BEE),非常巧合Zigbee也带一个BEE,看来物联网应该是蜜蜂建立的。BEE2-SDK-v1.2.0可从www.realmcu.com获得

        原始工程路径:BEE2-SDK-v1.2.0\board\evb\ble_peripheral\peripheral.uvprojx

        官方SDK有很多工程例子,本文用的是ble_peripheral

        peripheral是外设意思,ble+peripheral

1、工程中的文件夹:

1、include(一些头文件,不需要修改)
2、lib(静态库,不需要修改)
3、cmsis(ARM的比较基础的东西,不需要修改)
4、peripheral(RTL8762的外设,sdk里有各种外设驱动源码,按需添加)
5、profile(一般不用修改,GATT的配置文件,可以建立自己的profile)
6、app(主要的应用实现,重点修改文件都在这里)

  2、 peripheral下的文件

        我加的这几个文件,源文件都在BEE2-SDK-v1.2.0\src\mcu\peripheral下,用什么加什么

rtl876x_io_dlps.c
rtl876x_uart.c
rtl876x_rcc.c
rtl876x_gpio.c

     uart用来串口通讯,gipo用来点灯

3、app下的文件

ancs.c(原工程自带)
app_task.c(原工程自带,rtos任务创建)
main.c(原工程自带,主文件,初始化调度)
peripheral_app.c(原工程自带,消息处理)
overlay_mgr.c(原工程自带)
uart.c

        只有UART.C是后来添加的,实现了UART基本封装,其他都是原有工程自带

        BLE编程主要是处理各类消息,由peripheral_app.c负责。

二、主要代码解释

1.main.c

        main.c是应用入口,实现了main函数如下:

int main(void)
{
    extern uint32_t random_seed_value;
    srand(random_seed_value);
    board_init();
    le_gap_init(APP_MAX_LINKS);
    gap_lib_init();
    app_le_gap_init();
    app_le_profile_init();
    pwr_mgr_init();
    task_init();
    os_sched_start();
		
    return 0;
}

        这里的main函数完全不用修改,所有的RTL8762的程序都是这么写的。

        board_init()是硬件初始化

        *gap*是GAP初始化,GAP是BLE的重要概念

        app_le_profile_init()是GATT初始化,GATT是BLE另一个重要概念

        task_init()是OS_IF(freertos)的任务初始化,实时操作系统的任务创建

        常用的应该就是这么几个

2.关于GAP、GATT的粗浅认识

        打个比方如果把蓝牙设备比作商店,那么GAP就是商店的基本信息,比如商店名,地理位置等。而GATT就是商店提供的服务,比如某一类商品,商品的价格,款式,尺寸。根据需要还可以上架新的GATT服务。

        如果用BLE手机调试工具来看如下图所示:

1951574a4675457188b07b10cd88de39.jpeg

其中,Generic Access就是GAP,Unknown Service 和Battery Service 是GATT

        为什么BLE手机调试工具可以识别Battery Service,而不能识别Unknown Service。那是因为蓝牙标准组织给GATT服务提供了统一的编号,Battery Service有统一的编号,所以被识别出来,而Unknown Service本来就是自定义的服务,程序提供的编号不在统一编码内,BLE手机调试工具也就无法识别。

3.board.h文件

        main.c 文件include了board.h文件 ,board.h文件是开发板定义文件。

        其中以下定义根据需要开启,本文用到了UART和GPIO,所以USE_UART_DLPS和USE_GPIO_DLPS赋值为1,此处很关键,否则程序无法正常运行:

/* if use any peripherals below, #define it 1 */
#define USE_I2C0_DLPS        0
#define USE_I2C1_DLPS        0
#define USE_TIM_DLPS         0
#define USE_QDECODER_DLPS    0
#define USE_IR_DLPS          0
#define USE_RTC_DLPS         0
#define USE_UART_DLPS        1
#define USE_ADC_DLPS         0
#define USE_SPI0_DLPS        0
#define USE_SPI1_DLPS        0
#define USE_SPI2W_DLPS       0
#define USE_KEYSCAN_DLPS     0
#define USE_DMIC_DLPS        0
#define USE_GPIO_DLPS        1
#define USE_PWM0_DLPS        0
#define USE_PWM1_DLPS        0
#define USE_PWM2_DLPS        0
#define USE_PWM3_DLPS        0

4.GPIO初始化

点灯用P4_0和P4_1

#define GPIO_OUTPUT_PIN_0       P4_0
#define GPIO_OUTPUT_PIN_1       P4_1
#define GPIO_PIN_OUTPUT         GPIO_GetPin(GPIO_OUTPUT_PIN_0)
#define GPIO_PIN_OUTPUT1        GPIO_GetPin(GPIO_OUTPUT_PIN_1)

 UART用P3_0和P3_1

#define UART_TX_PIN                P3_0
#define UART_RX_PIN                P3_1

  board初始化: PAD(管脚)、UART

void board_init(void)
{
		/**
		*		@ led gpio init
		*/
Pad_Config(GPIO_OUTPUT_PIN_0, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE,
               PAD_OUT_HIGH);

Pinmux_Config(GPIO_OUTPUT_PIN_0, DWGPIO);
	
Pad_Config(GPIO_OUTPUT_PIN_1, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE,
               PAD_OUT_HIGH);

Pinmux_Config(GPIO_OUTPUT_PIN_1, DWGPIO);
	
		/**
		*	@ uart
		*/
		board_uart_init();
}

 void board_uart_init(void)

void board_uart_init(void)
{
    Pad_Config(UART_TX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
    Pad_Config(UART_RX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);

    Pinmux_Config(UART_TX_PIN, UART0_TX);
    Pinmux_Config(UART_RX_PIN, UART0_RX);

}

  设备初始化:GPIO、UART

void driver_init(void)
{
	/* Initialize GPIO */
    RCC_PeriphClockCmd(APBPeriph_GPIO, APBPeriph_GPIO_CLOCK, ENABLE);

    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin    = GPIO_PIN_OUTPUT|GPIO_PIN_OUTPUT1;
    GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_OUT;
    GPIO_InitStruct.GPIO_ITCmd  = DISABLE;
    GPIO_Init(&GPIO_InitStruct);
	
		//GPIO_InitStruct.GPIO_Pin    = GPIO_PIN_OUTPUT1;
		//GPIO_Init(&GPIO_InitStruct);
	
	//lightUpLed();
	/* uart init*/
		driver_uart_init();
}

 void driver_uart_init(void)

void driver_uart_init(void)
{
    UART_DeInit(UART);

    RCC_PeriphClockCmd(APBPeriph_UART0, APBPeriph_UART0_CLOCK, ENABLE);

    /* uart init */
    UART_InitTypeDef UART_InitStruct;
    UART_StructInit(&UART_InitStruct);

    /* Config uart baudrate */
    UART_InitStruct.div            = BaudRate_Table[BAUD_RATE_115200].div;
    UART_InitStruct.ovsr           = BaudRate_Table[BAUD_RATE_115200].ovsr;
    UART_InitStruct.ovsr_adj       = BaudRate_Table[BAUD_RATE_115200].ovsr_adj;

    UART_InitStruct.parity         = UART_PARITY_NO_PARTY;
    UART_InitStruct.stopBits       = UART_STOP_BITS_1;
    UART_InitStruct.wordLen        = UART_WROD_LENGTH_8BIT;
    UART_InitStruct.rxTriggerLevel = 16;                      //1~29
    UART_InitStruct.idle_time      = UART_RX_IDLE_2BYTE;      //idle interrupt wait time

    UART_Init(UART, &UART_InitStruct);
	
	
 uart_sendString1("####   #      #####         #   #    #    ####   #####         #      #####  ####  \r\n");
 uart_sendString1(" #  #  #      #             #   #   # #   #   #    #           #      #       #  # \r\n");
 uart_sendString1(" #  #  #      #             #   #  #   #  #   #    #           #      #       #  # \r\n");
 uart_sendString1(" ###   #      ####          #   #  #   #  ####     #           #      ####    #  # \r\n");
 uart_sendString1(" #  #  #      #             #   #  #####  # #      #           #      #       #  # \r\n");
 uart_sendString1(" #  #  #      #             #   #  #   #  #  #     #           #      #       #  # \r\n");
 uart_sendString1("####   #####  #####          ###   #   #  #   #    #           #####  #####  ####  \r\n");
 uart_sendString1("                     #####                              #####                      \r\n");
 uart_sendString1("Sarting......");   	                                                                              
}

 5.点灯函数

/*低电平点灯*/
void lightUpLed(void)
{
/* Light up LED0 */
    GPIO_WriteBit(GPIO_PIN_OUTPUT, (BitAction)(0));
    GPIO_WriteBit(GPIO_PIN_OUTPUT1,(BitAction)(0));
}

/*高电平灭灯*/
void lightDownLed(void)
{
/* Light down LED0 */
   GPIO_WriteBit(GPIO_PIN_OUTPUT, (BitAction)(1));
   GPIO_WriteBit(GPIO_PIN_OUTPUT1,(BitAction)(1));
}

/*闪灯*/
void flashLed(void)
{
	for(uint32_t j=0;j<5;j++)
	{
		lightUpLed();
		for (uint32_t i = 0; i < 100000; i++);
		lightDownLed();
	}
}

 6、UART串口发送

其中uart_senddata_continuous是官方DEMO里的函数

void uart_sendString1(char* str)
{
	uint16_t demo_str_len = 0;
	demo_str_len = strlen(str);
  memcpy(String_Buf1, str, demo_str_len);

  /* Send demo tips */
  uart_senddata_continuous(UART, String_Buf1, demo_str_len);
}

7、处理消息点灯,发送UART信息

在peripheral_app.c中,查找“BAS_READ_BATTERY_LEVEL”做如下修改

改成静态变量:static uint8_t battery_level = 90;

添加:battery_level++;

添加用于点灯:lightUpLed();

添加用于UART输出信息:uart_sendString1("Get BATTERY LEVEL\r\n");

case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE:
            {
                if (p_bas_cb_data->msg_data.read_value_index == BAS_READ_BATTERY_LEVEL)
                {
                    static uint8_t battery_level = 90;
                    APP_PRINT_INFO1("BAS_READ_BATTERY_LEVEL: battery_level %d", battery_level);
										
										uart_sendString1("Get BATTERY LEVEL\r\n");
                    bas_set_parameter(BAS_PARAM_BATTERY_LEVEL, 1, &battery_level);
										battery_level++;
										//trun_led(0);
										lightUpLed();
										
                }
            }

8.蓝牙未连接时LED闪烁,连接时LED熄灭

app_task.c中增加timer的任务,回调函数是timer_callback;

另外用task方式建了一个uart任务,实验task方式处理UART。

void app_task_init()
{
//		void *p_handle=NULL;
    os_task_create(&app_task_handle, "app", app_main_task, 0, APP_TASK_STACK_SIZE,
                   APP_TASK_PRIORITY);
	
	//timer task
	
	if(os_timer_create(&p_handle,"timer",0,1000,true,timer_callback )== true)
		{
			os_timer_start(&p_handle);
		}
		else
		{
			//Timer failed to creat.
		}
	
		//uart task
		os_task_create(&uart_task_handle, "uart", uart_task, 0, APP_TASK_STACK_SIZE,
                   APP_TASK_PRIORITY);
		

	
}

 timer的任务的处理函数,回调函数负责闪烁LED(用了PAD方式,不是GPIO),timer_stop负责停止定时,闪烁停止;timer_restart负责重新定时,继续闪烁。

oid timer_callback(void *p_handle)
{

	static uint8_t count =0;
	if(count == 0)
	{
		Pad_Config(P4_0,PAD_SW_MODE,PAD_IS_PWRON,PAD_PULL_NONE,PAD_OUT_ENABLE,PAD_OUT_LOW);
		count = 1;
	}
	else{
		Pad_Config(P4_0,PAD_SW_MODE,PAD_IS_PWRON,PAD_PULL_NONE,PAD_OUT_ENABLE,PAD_OUT_HIGH);
		count = 0;
	}
	
}


void timer_stop(void){
	os_timer_stop(&p_handle);
	Pad_Config(P4_0,PAD_SW_MODE,PAD_IS_PWRON,PAD_PULL_NONE,PAD_OUT_ENABLE,PAD_OUT_HIGH);
}

void timer_restart(void){
	os_timer_restart(&p_handle,100);
}

 在peripheral_app.c中,查找“GAP_CONN_STATE_DISCONNECTED”,增加timer_restart(),实现在蓝牙断开后,LED继续闪烁。在“GAP_CONN_STATE_CONNECTED”后面增加timer_stop();,实现蓝牙连接后,LED停止闪烁。

case GAP_CONN_STATE_DISCONNECTED:
        {
            if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE))
                && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE)))
            {
                APP_PRINT_ERROR1("app_handle_conn_state_evt: connection lost cause 0x%x", disc_cause);
            }

            le_adv_start();
						timer_restart();
        }

        break;

    case GAP_CONN_STATE_CONNECTED:
        {
            uint16_t conn_interval;
            uint16_t conn_latency;
            uint16_t conn_supervision_timeout;
            uint8_t  remote_bd[6];
            T_GAP_REMOTE_ADDR_TYPE remote_bd_type;

            le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id);
            le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id);
            le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id);
            le_get_conn_addr(conn_id, remote_bd, &remote_bd_type);
            APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x",
                            TRACE_BDADDR(remote_bd), remote_bd_type,
                            conn_interval, conn_latency, conn_supervision_timeout);
					
						timer_stop();
						
        }

总结

1、源码这里下载https://download.csdn.net/download/weixin_44067125/87995309

2、主要实现以下功能:

        BATTERY LEVEL 读取电量自增1、点亮LED

        自定义characteristic 发送HEX数据:0A点亮led,发送14熄灭led,发送其他LED闪烁

        蓝牙未连接时,LED闪烁,连接时LED熄灭 

3、BLE基本概念需要了解

4、RTOS实时操作系统要了解一些,至少知道创建task

5、KEIL编译,MPTOOL烧写

6、手机上的BLE调试工具需要安一个,我用的是沁恒家的

7、板子:RTL8762C 开发板 - 嘉立创EDA开源硬件平台

RTL8762的手册和SDK前前后后看了一个月,终于可以点灯。小白自学没办法,都是新知识,卡在一个地方好久都出不来。

3d55b137e4164b66b6ba0dffa6e94c19.jpg

UART串口助手接收信息:

 发送14(HEX)灭LED

 接收电量信息,每次加1,LED亮

 

发送0A(HEX),LED亮 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44067125/article/details/131529485

智能推荐

while循环&CPU占用率高问题深入分析与解决方案_main函数使用while(1)循环cpu占用99-程序员宅基地

文章浏览阅读3.8k次,点赞9次,收藏28次。直接上一个工作中碰到的问题,另外一个系统开启多线程调用我这边的接口,然后我这边会开启多线程批量查询第三方接口并且返回给调用方。使用的是两三年前别人遗留下来的方法,放到线上后发现确实是可以正常取到结果,但是一旦调用,CPU占用就直接100%(部署环境是win server服务器)。因此查看了下相关的老代码并使用JProfiler查看发现是在某个while循环的时候有问题。具体项目代码就不贴了,类似于下面这段代码。​​​​​​while(flag) {//your code;}这里的flag._main函数使用while(1)循环cpu占用99

【无标题】jetbrains idea shift f6不生效_idea shift +f6快捷键不生效-程序员宅基地

文章浏览阅读347次。idea shift f6 快捷键无效_idea shift +f6快捷键不生效

node.js学习笔记之Node中的核心模块_node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是-程序员宅基地

文章浏览阅读135次。Ecmacript 中没有DOM 和 BOM核心模块Node为JavaScript提供了很多服务器级别,这些API绝大多数都被包装到了一个具名和核心模块中了,例如文件操作的 fs 核心模块 ,http服务构建的http 模块 path 路径操作模块 os 操作系统信息模块// 用来获取机器信息的var os = require('os')// 用来操作路径的var path = require('path')// 获取当前机器的 CPU 信息console.log(os.cpus._node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是

数学建模【SPSS 下载-安装、方差分析与回归分析的SPSS实现(软件概述、方差分析、回归分析)】_化工数学模型数据回归软件-程序员宅基地

文章浏览阅读10w+次,点赞435次,收藏3.4k次。SPSS 22 下载安装过程7.6 方差分析与回归分析的SPSS实现7.6.1 SPSS软件概述1 SPSS版本与安装2 SPSS界面3 SPSS特点4 SPSS数据7.6.2 SPSS与方差分析1 单因素方差分析2 双因素方差分析7.6.3 SPSS与回归分析SPSS回归分析过程牙膏价格问题的回归分析_化工数学模型数据回归软件

利用hutool实现邮件发送功能_hutool发送邮件-程序员宅基地

文章浏览阅读7.5k次。如何利用hutool工具包实现邮件发送功能呢?1、首先引入hutool依赖<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.19</version></dependency>2、编写邮件发送工具类package com.pc.c..._hutool发送邮件

docker安装elasticsearch,elasticsearch-head,kibana,ik分词器_docker安装kibana连接elasticsearch并且elasticsearch有密码-程序员宅基地

文章浏览阅读867次,点赞2次,收藏2次。docker安装elasticsearch,elasticsearch-head,kibana,ik分词器安装方式基本有两种,一种是pull的方式,一种是Dockerfile的方式,由于pull的方式pull下来后还需配置许多东西且不便于复用,个人比较喜欢使用Dockerfile的方式所有docker支持的镜像基本都在https://hub.docker.com/docker的官网上能找到合..._docker安装kibana连接elasticsearch并且elasticsearch有密码

随便推点

Python 攻克移动开发失败!_beeware-程序员宅基地

文章浏览阅读1.3w次,点赞57次,收藏92次。整理 | 郑丽媛出品 | CSDN(ID:CSDNnews)近年来,随着机器学习的兴起,有一门编程语言逐渐变得火热——Python。得益于其针对机器学习提供了大量开源框架和第三方模块,内置..._beeware

Swift4.0_Timer 的基本使用_swift timer 暂停-程序员宅基地

文章浏览阅读7.9k次。//// ViewController.swift// Day_10_Timer//// Created by dongqiangfei on 2018/10/15.// Copyright 2018年 飞飞. All rights reserved.//import UIKitclass ViewController: UIViewController { ..._swift timer 暂停

元素三大等待-程序员宅基地

文章浏览阅读986次,点赞2次,收藏2次。1.硬性等待让当前线程暂停执行,应用场景:代码执行速度太快了,但是UI元素没有立马加载出来,造成两者不同步,这时候就可以让代码等待一下,再去执行找元素的动作线程休眠,强制等待 Thread.sleep(long mills)package com.example.demo;import org.junit.jupiter.api.Test;import org.openqa.selenium.By;import org.openqa.selenium.firefox.Firefox.._元素三大等待

Java软件工程师职位分析_java岗位分析-程序员宅基地

文章浏览阅读3k次,点赞4次,收藏14次。Java软件工程师职位分析_java岗位分析

Java:Unreachable code的解决方法_java unreachable code-程序员宅基地

文章浏览阅读2k次。Java:Unreachable code的解决方法_java unreachable code

标签data-*自定义属性值和根据data属性值查找对应标签_如何根据data-*属性获取对应的标签对象-程序员宅基地

文章浏览阅读1w次。1、html中设置标签data-*的值 标题 11111 222222、点击获取当前标签的data-url的值$('dd').on('click', function() { var urlVal = $(this).data('ur_如何根据data-*属性获取对应的标签对象

推荐文章

热门文章

相关标签