完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
` 本帖最后由 MMCU5721167 于 2020-1-15 13:06 编辑 在前面一个章节中我们详细介绍了基于MM32W系列芯片的串口透传应用,该应用可以实现丰富的数据透传方案,在本章节我们将再给大家介绍一个简易而扩展性较强的应用方案——基于MM32W系列开发的数据采集仪器。 图1 方案应用图 在工业控制现场,常常需要实时采集大量的现场数据,如电压、电流、温度、湿度、气压等,往往这些小信号都是需要输入到专业的数据采集模块中进行处理,后者又将采集的数据传输到主机进行处理,由主机根据处理的结果,将控制信号传输给现场执行模块进行各种操作。目前数据的传输基本是基于有线的网络,如RS485,CAN等。这些有线的网络一般具有成本比较高、维护不方便等缺点。而无线传输相对具有一定的优势,如成本低、可靠性高、维护方便等。本文将介绍一个基于MM32W系列MCU的简易蓝牙数据采集系统实现过程。 硬件资源如下: 本方案基于MM32 BLE_Test Board进行测试验证,为了简易模拟实现传感器信号的采集与处理过程,在硬件原理上,本方案直接使用DEMO板上自带的ADC电位器RV1来调节不同的输入信号情况,该信号连接到引脚PB0上,该引脚可复用为AD采样通道CH8;使用PB1连接到绿色LED指示灯,可作为蓝牙连接状态的指示,且低功耗唤醒引脚选择PA0配置为下拉输入;蓝牙相关的功能引脚与前面介绍的方案一致,此处不做过多展开。 图2 硬件原理图 软件资源如下: 结合上述使用到的硬件资源,下面我们着重介绍软件实现流程以及相关配置代码,主要涉及ADC模拟通道以及相应引脚的配置,加上ADC采样的配置及使用。 以下为主函数初始化配置及相关全局变量定义内容,主要将所有的外设资源、蓝牙广播报文以及蓝牙协议栈初始化,并且以阻塞的的方式运行蓝牙,代码如下: const unsigned char AdvDat_HRS[]= {//定义广播报文 0x02,0x01,0x06, 0x03,0x19,0x41,0x03, 0x07,0x03,0x0D,0x18,0x0A,0x18,0x0F,0x18 }; int main(void) { BSP_Init();//初始化 SPI IO 以及ADC radio_initBle(TXPWR_0DBM, &ble_mac_addr);//初始化蓝牙芯片及蓝牙协议栈,并且定义发射功率 ble_set_adv_data((unsigned char *)AdvDat_HRS, sizeof(AdvDat_HRS));//设置BLE广播数据 Systick_Count = 0; while(SysTick_Count <= 1500){};//在初始化蓝牙协议栈后等待至少5ms才能正式运行蓝牙 Write_Iwdg_ON(IWDG_Prescaler_32, 0x4E2); //设置IWDG看门狗防止程序跑飞,1s不喂狗系统重启 ble_run(160*2); //采用堵塞方式运行蓝牙协议,广播间隔时间为 200ms } 下面再介绍一下ADC操作相关的几个函数: //在需要往APP上报实时ADC转换数值时调用下面获取ADC通道平均采样值的函数 /******************************************************************************************************** **函数信息 :Get_Adc_Average(uint8_t ADC_Channel_x,uint8_t times) **功能描述 :获取几次ADC1采样值的平均值 **输入参数 :ADC_Channel_x , x为0~11 **输出参数 :puiADData为ADC读到的值 ********************************************************************************************************/ u16 Get_Adc_Average(uint8_t ADC_Channel_x,uint8_t times) { u32 temp_val=0; u8 t; u8 delay; for(t=0;t temp_val+=ADC1_SingleChannel_Get(ADC_Channel_x); for(delay=0;delay<100;delay++); } return temp_val/times; } /*************************************************************************************************** **函数信息 :ADC1_SingleChannel_Get() **功能描述 :获取ADC1转换数据 **输入参数 :ADC_Channel_x , x为0~11 *puiADData ,ADC1实际转换数据 **输出参数 :ucStatus ,0 表示数据获取失败,1 表示成功 ***************************************************************************************************/ u16 ADC1_SingleChannel_Get(uint8_t ADC_Channel_x) { u16 puiADData; ADC_SoftwareStartConvCmd(ADC1, ENABLE); // ADCR寄存器的ADST位使能,软件启动转换 while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==0); //等待ADC转换完成标志位置位 ADC_ClearFlag(ADC1, ADC_FLAG_EOC);//清除ADC转换完成标志位置位 puiADData=ADC1->ADDATA&0xfff;//读取ADC转换值 return puiADData; } /******************************************************************************************************** **函数信息 :void ADC1_SingleChannel(uint8_t ADC_Channel_x) **功能描述 :配置ADC1单次转换模式 **输入参数 :ADC_Channel_x , x为0~11 **输出参数 :无 ********************************************************************************************************/ void ADC1_SingleChannel(uint8_t ADC_Channel_x) { ADC_InitTypeDef ADC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); ADC_InitStructure.ADC_PRESCARE = ADC_PCLK2_PRESCARE_16;//初始化ADC分频 ADC_InitStructure.ADC_Mode = ADC_Mode_Single;//初始化ADC工作模式 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//禁止连续转换 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //初始化ADC转换对齐方式 ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//初始化ADC采样精度 ADC_Init(ADC1, &ADC_InitStructure);//初始化ADC ADC_RegularChannelConfig(ADC1, DISABLE_ALL_CHANNEL , 0, 0); //屏蔽所有ADC通道 ADC_RegularChannelConfig(ADC1, ADC_Channel_x, 0, ADC_SampleTime_13_5Cycles); //使能选中通道 if(ADC_Channel_x == ADC_Channel_11) { ADC_VrefintCmd(ENABLE);//如果为通道11,则使能内部参考电压 } ADC_Cmd(ADC1, ENABLE); //使能ADC1 } 我们在gatt_user_send_notify_data_callback函数中给手机发送数据,该函数属于回调函数,协议栈会在系统允许的时候(异步)回调本函数,该函数可用于蓝牙模块端主动发送数据之用,函数内部不得增加阻塞代码。在本应用中我们在此函数中实现将ADC采集并且转换后的数据传输给手机APP。详细实现代码如下: //蓝牙连接成功后协议在空闲的时候会调用本回调函数 void gatt_user_send_notify_data_callback(void){ static unsigned char HRMData[3]={0x00,0x00,0x01};//定义装载ADC值的存储区 static unsigned char SimBatt=100;//定义装载ADC 百分数值的存储区 static u8 Cont=0;//回调次数计数器 u16 Val=0; Cont++; //每进一次该函数回调次数计数器+1 if (Cont >= 20) {//每进入该回调函数20次才发送一次ADC数据 Cont = 0; Val = Get_Adc_Average(ADC_Channel_3,5); //获取5次ADC转换的平均值 Val = Val>>3; // 0~511 for HRM data cur_notifyhandle = 0x12;//ADC数据回复句柄值 if (Val<0x100) { HRMData[0] = 0; //1Byte HRMData[1] = Val; sconn_notifydata(HRMData,2);//换算处理好ADC数据后通过蓝牙发出 } else { HRMData[0] = 1; //2Byte HRMData[1] = Val; HRMData[2] = Val>>8; sconn_notifydata(HRMData,3);//换算处理好ADC数据后通过蓝牙发出 } } else if (10 == Cont) {//每进入该回调函数10次才发送一次ADC数据 Val = Get_Adc_Average(ADC_Channel_3,5); //获取5次ADC转换的平均值 Val = Val>>3; SimBatt = (Val*100)>>9; //0~100 cur_notifyhandle = 0x18;//ADC百分数形式数据回复句柄值 sconn_notifydata(&SimBatt,1);/换算处理好ADC百分数后通过蓝牙发出 } } 除了上述关键的蓝牙数据发送函数外,下面再简单介绍一些与蓝牙相关的特征值定义: 在const BLE_CHAR AttCharList[] 中定义了本案中的两个特征值: {TYPE_CHAR,0x11,ATT_CHAR_PROP_NTF, 0x12,0, 0x37,0x2A, UUID16_FORMAT},//ADC数值 {TYPE_CHAR,0x17,ATT_CHAR_PROP_RD|ATT_CHAR_PROP_NTF, 0x18,0,0x19,0x2A,UUID16_FORMAT},//百分数形式 在void att_server_rdByGrType( u8 pdu_type, u8 attOpcode, u16 st_hd, u16 end_hd, u16 att_type )中实现了自定义特征值服务声明。 手机操作流程如下: 打开手机蓝牙并打开 App,选择HRM进入,点击Connect按钮开始搜索温湿度蓝牙设备。 选择对应名称(MM32W0_ADC)的蓝牙设备并进行配对,等待连接成功。连接成功后会有相应提示,按钮Connect名字会变成Disconnect。 连接成功后,在App界面上电池图标会显示从DEMO板上的电位器分压得来的ADC数据信息(经过关系换算或以百分比形式,非实际转换值)。 |
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
2245个成员聚集在这个小组
加入小组灵动微电子MM32全系列MCU产品应用手册,库函数和例程和选型表
11525 浏览 3 评论
【MM32 eMiniBoard试用连载】+基于OLED12864的GUI---U8G2
5902 浏览 1 评论
【MM32 eMiniBoard试用连载】移植RT-Thread至MM32L373PS
10823 浏览 0 评论
【MM32 eMiniBoard测评报告】+ 开箱 + 初探
4554 浏览 1 评论
灵动微课堂(第106讲) | MM32 USB功能学习笔记 —— WinUSB设备
4280 浏览 1 评论
[MM32软件] MM32F002使用内部flash存储数据怎么操作?
944浏览 1评论
768浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-7 16:36 , Processed in 0.671348 second(s), Total 60, Slave 45 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号