PAN1020 SDK中有一个点灯程序,位于:01_SDK\BLE_APP\keil_projects\proj_rgb_light。
既然有现成的轮子就不重新造了,本文对这个程序做个粗浅的解读。
一、arch_main.c
蓝牙广播的名称在这里改,这个“b+EMIE Elfy",就是蓝牙广播的名称。
const app_info_t app_info __attribute__((at(APP_INFO_ADDR)))=
{
.co_default_bdname = "b+EMIE Elfy",
.default_use_ext_32k = USE_EXT_32K,
.default_hz32000 = HZ32000,
.default_en_calib_rc = EN_CALIB_RC,
.default_calib_slot = CALIB_SLOTS,
.default_calib_32k_int = 96000,
};
二、proj_rgb.c
rgb_start_advertising函数负责GAP的开启广播
void rgb_start_advertising(void)
{
struct gapm_start_advertise_cmd msg;
uint8_t *pos ;
msg.op.code = GAPM_ADV_UNDIRECT;
msg.op.addr_src = GAPM_STATIC_ADDR;
msg.intv_min = 32;
msg.intv_max = 50;
msg.channel_map = APP_ADV_CHMAP;
msg.info.host.mode = GAP_GEN_DISCOVERABLE;
msg.info.host.adv_filt_policy = ADV_ALLOW_SCAN_ANY_CON_ANY;
pos = msg.info.host.scan_rsp_data;
*pos++ = 17;//Length
*pos++ = '\x07';//type UUID
//Raw UUID: 0x 6e 40 20 01 b5 a3 f3 93 e0 a9 e5 0e 24 dc ca 9e
memcpy(pos, "\x9e\xca\xdc\x24\x0e\xe5\xa9\xe0\x93\xf3\xa3\xb5\x01\x20\x40\x6e",strlen("\x6e\x40\x20\x01\xb5\xa3\xf3\x93\xe0\xa9\xe5\x0e\x24\xdc\xca\x9e"));
pos += strlen("\x6e\x40\x20\x01\xb5\xa3\xf3\x93\xe0\xa9\xe5\x0e\x24\xdc\xca\x9e");
msg.info.host.scan_rsp_data_len = ((uint32_t)pos - (uint32_t)(msg.info.host.scan_rsp_data));
msg.info.host.adv_data[0] = 0x2;
msg.info.host.adv_data[1] = 0x1;
msg.info.host.adv_data[2] = 0x6;
pos = &msg.info.host.adv_data[3];
*pos++=strlen(app_info.co_default_bdname)+1;
*pos++ = '\x09';
memcpy(pos, app_info.co_default_bdname, strlen(app_info.co_default_bdname));
pos+=strlen(app_info.co_default_bdname);
*pos++ = '\x0b';
*pos++ = '\xff';
*pos++ = '\x11';
*pos++ = '\x00';
memcpy(pos,"\xc9\x7a\xbb\x8f\xdd\x4b\x00\x11",sizeof("\xc9\x7a\xbb\x8f\xdd\x4b\x00\x11"));
pos+=sizeof("\xc9\x7a\xbb\x8f\xdd\x4b\x00\x11");
msg.info.host.adv_data_len = ((uint32_t)pos - (uint32_t)(msg.info.host.adv_data))-1;
appm_start_advertising(&msg);
}
light_set_rgb函数负责设置RGB灯的控制,RGB需要PWM控制
void light_set_rgb(uint8_t r,uint8_t g,uint8_t b)
{
r=100-r;
g=100-g;
b=100-b;
if(g==100||g==0)
{//p24
SYS->P2_MFP=SYS->P2_MFP&(~(SYS_MFP_P24_Msk));//init Gpio
GPIO_SetMode(P2,BIT4,GPIO_MODE_OUTPUT);
P24=(g==100?1:0);
}
else
{
SYS->P2_MFP|= SYS_MFP_P24_PWM0_CH2;
PWM_ConfigOutputChannel(PWM, 2, 200, g);//g
}
if(r==100||r==0)
{//p25
SYS->P2_MFP=SYS->P2_MFP&(~(SYS_MFP_P25_Msk));//init Gpio
GPIO_SetMode(P2,BIT5,GPIO_MODE_OUTPUT);
P25=(r==100?1:0);
}
else
{
SYS->P2_MFP|= SYS_MFP_P25_PWM0_CH3;
PWM_ConfigOutputChannel(PWM, 3, 200, r);//r
}
if(b==100||b==0)
{//p26
SYS->P2_MFP=SYS->P2_MFP&(~(SYS_MFP_P26_Msk));//init Gpio
GPIO_SetMode(P2,BIT6,GPIO_MODE_OUTPUT);
P26=(b==100?1:0);
}
else
{
SYS->P2_MFP|= SYS_MFP_P26_PWM0_CH4;
PWM_ConfigOutputChannel(PWM, 4, 200, b);//b
}
}
light_init()负责初始化RGB用到的GPIO。
void light_init()
{
SYS->P2_MFP |= SYS_MFP_P24_PWM0_CH2 | SYS_MFP_P25_PWM0_CH3|SYS_MFP_P26_PWM0_CH4;
PWM_EnableOutput(PWM,((1<<2)|(1<<3)|(1<<4)));
light_set_rgb(0,0,100);
PWM_Start(PWM,((1<<2)|(1<<3)|(1<<4)));
}
三、rgb_server1.c
关于GATT的定义和初始化。
///Service1
#define PRIM_2001 {0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,0xf3,0xa3,0xb5,0x01,0x20,0x40,0x6e}
#define C2003_UUID {0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,0xf3,0xa3,0xb5,0x03,0x20,0x40,0x6e}
#define C2002_UUID {0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,0xf3,0xa3,0xb5,0x02,0x20,0x40,0x6e}
定义了点灯GATT服务的UUID:PRIM_2001,还有该服务下了2个Charactericstic的UUID,对应BLE调试工具就是:
其中2002就后面要用来点灯用。
四、app_rgb_light1.c
static int rgb_server1_peer_write_data_ind_handler(ke_msg_id_t const msgid,
struct rgb_server1_peer_write_data_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
uint8_t data[2]={0x16,0xbb};
const uint8_t arr1[10] = {0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00};
const uint8_t arr2[10] = {0x00,0x00,0x00,0x01,0x04,0x00,0x00,0x00,0x00,0x00};
if(memcmp(param->packet,arr1,10) == 0 || memcmp(param->packet,arr2,10) == 0)
{
}
else
{
show_reg3(param->packet,param->packet_size);
}
//Set RGB
if((param->packet_size==5)&&(param->packet[0]==0xAA)&&(param->packet[1]==0x16))
{
light_set_rgb(param->packet[2]*10,param->packet[3]*10,param->packet[4]*10);
}
else if((param->packet_size==2)&&(param->packet[0]==0xAA)&&(param->packet[1]==0x03))
{
printf("close light\r\n");
light_set_rgb(0,0,0);
}
app_rgb1_send_value(RGB_SERVERICE1_IDX_10,data,2);
return (KE_MSG_CONSUMED);
}
rgb_server1_peer_write_data_ind_handler负责对收到手机蓝牙调试工具发来的控制信息进行处理并控制点灯
1、show_reg3(param->packet,param->packet_size);实现透传到电脑串口打印输出。
前提是输入字符串非
{0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00}或{0x00,0x00,0x00,0x01,0x04,0x00,0x00,0x00,0x00,0x00}
2、点灯
//Set RGB
if((param->packet_size==5)&&(param->packet[0]==0xAA)&&(param->packet[1]==0x16))
{
light_set_rgb(param->packet[2]*10,param->packet[3]*10,param->packet[4]*10);
}
else if((param->packet_size==2)&&(param->packet[0]==0xAA)&&(param->packet[1]==0x03))
{
printf("close light\r\n");
light_set_rgb(0,0,0);
}
输入为:AA16nnnnnn,其中AA16代表点灯指令,nnnnnn为RGB值,每个nn取值:0x00<=nn<=0x64。
输入为:AA03,灭灯
五、总结
1、PAN1020的SDK可以从磐启微官方BBS中下载。
2、SDK中有个《PAN1020 SDK工程介绍及使用指南》,但只看这个还是有难度。
3、PAN的SDK整体感觉不是特别清晰,调用关系很难理清。
4、PAN1020程序烧写可参考PAN1020 SWD方式程序下载(烧写)_修充电器上瘾的博客-CSDN博客
5、本人功力有限,其实大部分程序都没看懂,上面解释的也不知道对不对。