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手机调试工具来看如下图所示:

RTL8762C SDK开发-点灯及UART_第1张图片

其中,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前前后后看了一个月,终于可以点灯。小白自学没办法,都是新知识,卡在一个地方好久都出不来。

RTL8762C SDK开发-点灯及UART_第2张图片

UART串口助手接收信息:

RTL8762C SDK开发-点灯及UART_第3张图片

 发送14(HEX)灭LED

RTL8762C SDK开发-点灯及UART_第4张图片

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

 RTL8762C SDK开发-点灯及UART_第5张图片

发送0A(HEX),LED亮 

RTL8762C SDK开发-点灯及UART_第6张图片

你可能感兴趣的:(单片机)