初始版本
This commit is contained in:
201
app/Src/IoControl.c
Normal file
201
app/Src/IoControl.c
Normal file
@@ -0,0 +1,201 @@
|
||||
/********************************************************************
|
||||
Copyright (c) 2021 Xiangyu Medical Co.,Ltd. All rights reserved.
|
||||
FileName : IoControl.c
|
||||
Author : zhangdawei
|
||||
Version : V1.0
|
||||
Date :
|
||||
Note :
|
||||
History :
|
||||
********************************************************************/
|
||||
/* Includes ------------------------------------------------------*/
|
||||
#include "IoControl.h"
|
||||
#include "drv_uart.h"
|
||||
#include "nrf_drv_gpiote.h"
|
||||
/* Private define ------------------------------------------------*/
|
||||
/* Private typedef -----------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------*/
|
||||
uint8_t LastState = Null; //保存上一次的状态
|
||||
/* Private function prototypes -----------------------------------*/
|
||||
/* Public constants ----------------------------------------------*/
|
||||
/* Public variables ----------------------------------------------*/
|
||||
DeviceStateInfo_e DeviceState = POWER_CLOSE; //设备开关机状态
|
||||
ChargingStateInfo_e ChargeState = Uncharged;
|
||||
ChargingStateInfo_e ChargeLastState = Uncharged;
|
||||
KeyStateInfo_t KeyStateInfo;
|
||||
/********************************************************************
|
||||
* name : void GpioInit(void)
|
||||
* description : GPIO引脚初始化
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void GpioInit(void)
|
||||
{
|
||||
NRF_UICR->NFCPINS = 0;
|
||||
|
||||
nrf_gpio_cfg_output(KEY_POWER);
|
||||
nrf_gpio_cfg_output(LED_YELLOW);
|
||||
// nrf_gpio_cfg_output(CHARGE_LED);
|
||||
|
||||
nrf_gpio_cfg_output(STIM_RMS_RELAY_PIN);
|
||||
nrf_gpio_cfg_output(STIM_RELAY_PIN);
|
||||
nrf_gpio_cfg_output(SAMPLE_POWER_PIN);
|
||||
|
||||
|
||||
// nrf_gpio_pin_clear(KEY_POWER);
|
||||
nrf_gpio_pin_clear(LED_YELLOW);
|
||||
|
||||
// nrf_gpio_pin_clear(CHARGE_LED);
|
||||
|
||||
nrf_gpio_pin_clear(STIM_RMS_RELAY_PIN);
|
||||
nrf_gpio_pin_clear(STIM_RELAY_PIN);
|
||||
nrf_gpio_pin_clear(SAMPLE_POWER_PIN);
|
||||
|
||||
/////////
|
||||
nrf_gpio_cfg_input(CHG_MANAGER_CHG, NRF_GPIO_PIN_NOPULL);//检测充电状态
|
||||
|
||||
}
|
||||
/* 电刺激输出使能脚 */
|
||||
void StimOutCtlOpen(void)
|
||||
{
|
||||
|
||||
}
|
||||
void StimOutCtlClose(void)
|
||||
{
|
||||
|
||||
}
|
||||
/* 能量释放控制 */
|
||||
void StimReleaseOpen(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void StimReleaseClose(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// OK按键处理函数
|
||||
void KEY_PWR_SWITICH_Handler(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//GPIOTE事件处理函回调函数,事件回调函数里面可以获取pin编号和引脚状态变化
|
||||
void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
|
||||
{
|
||||
if(pin == KEY_PWR_SWITICH)
|
||||
{
|
||||
|
||||
KeyStateInfo.shineng = true;
|
||||
KeyStateInfo.KeyPinNumber = KEY_PWR_SWITICH;
|
||||
}
|
||||
}
|
||||
void EXIT_KEY_Init(void)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
|
||||
nrf_gpio_cfg_input(KEY_PWR_SWITICH, NRF_GPIO_PIN_PULLUP);//检测开关机信号
|
||||
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void open_acquisition_relay(void)
|
||||
* description : 打开采样继电器
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void open_acquisition_relay(void)
|
||||
{
|
||||
nrf_gpio_pin_set(STIM_RMS_RELAY_PIN); //闭合继电器
|
||||
nrf_gpio_pin_clear(STIM_RELAY_PIN); //打开刺激继电器
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void close_acquisition_relay(void)
|
||||
* description : 关闭采样继电器
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void close_acquisition_relay(void)
|
||||
{
|
||||
nrf_gpio_pin_clear(STIM_RMS_RELAY_PIN);
|
||||
nrf_gpio_pin_clear(STIM_RELAY_PIN);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* name : void open_stimulate_relay(void)
|
||||
* description : 打开刺激继电器
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void open_stimulate_relay(void)
|
||||
{
|
||||
nrf_gpio_pin_clear(STIM_RMS_RELAY_PIN);
|
||||
nrf_gpio_pin_set(STIM_RELAY_PIN);
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void close_stimulate_relay(void)
|
||||
* description : 关闭刺激继电器
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void close_stimulate_relay(void)
|
||||
{
|
||||
nrf_gpio_pin_clear(STIM_RMS_RELAY_PIN);
|
||||
nrf_gpio_pin_clear(STIM_RELAY_PIN);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* name : void StimStateInfoStructInit(SchemeData_t SchemeDataIn)
|
||||
* description : 初始化通道信息描述结构体
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void StimStateInfoStructInit(SchemeData_t SchemeDataIn)
|
||||
{
|
||||
|
||||
}
|
||||
// 设备预存信息初始化ID :101 腹直肌分离
|
||||
void PreStorageSchemeDataInit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void KeyPinHandler(void)
|
||||
{
|
||||
if(KeyStateInfo.shineng == true)
|
||||
{
|
||||
switch(KeyStateInfo.KeyPinNumber)
|
||||
{
|
||||
case KEY_PWR_SWITICH:
|
||||
{
|
||||
KEY_PWR_SWITICH_Handler();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
KeyStateInfo.shineng = false;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void VariableInit(void)
|
||||
* description : 初始化变量
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void VariableInit(void)
|
||||
{
|
||||
|
||||
}
|
||||
/*************************** END OF FILE ***************************/
|
||||
|
||||
364
app/Src/drv_saadc.c
Normal file
364
app/Src/drv_saadc.c
Normal file
@@ -0,0 +1,364 @@
|
||||
/********************************************************************
|
||||
Copyright (c) 2021 Xiangyu Medical Co.,Ltd. All rights reserved.
|
||||
FileName : drv_saadc.c
|
||||
Author : zhangdawei
|
||||
Version : V1.0
|
||||
Date :
|
||||
Note :
|
||||
History :
|
||||
********************************************************************/
|
||||
/* Includes ------------------------------------------------------*/
|
||||
#include "nrf_drv_ppi.h"
|
||||
#include "app_timer.h"
|
||||
#include "bsp_btn_ble.h"
|
||||
#include "drv_saadc.h"
|
||||
#include "timer.h"
|
||||
#include "string.h"
|
||||
#include "drv_uart.h"
|
||||
#include "nrf_drv_ppi.h"
|
||||
#include "IIR.h"
|
||||
/* Private define ------------------------------------------------*/
|
||||
/* Private typedef -----------------------------------------------*/
|
||||
#define SAMPLES_BUFFER_LEN 10
|
||||
/* Private constants ---------------------------------------------*/
|
||||
//定义Timer1的驱动程序实例。驱动程序实例的ID对应Timer的ID,如NRF_DRV_TIMER_INSTANCE(1)对应Timer1
|
||||
const nrfx_timer_t TIMER_ADC = NRF_DRV_TIMER_INSTANCE(4);
|
||||
static nrf_ppi_channel_t m_ppi_channel5;
|
||||
const nrfx_timer_t TIMER3_RMS = NRFX_TIMER_INSTANCE(3); //读取rms值的定时器3
|
||||
static nrf_saadc_value_t m_buffer_pool[2][SAMPLES_BUFFER_LEN];
|
||||
/* Private variables ---------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------*/
|
||||
/* Public constants ----------------------------------------------*/
|
||||
/* Public variables ----------------------------------------------*/
|
||||
//电池电压回调函数,堵塞模式,不需要事件,定义空的事件回调函数
|
||||
void saadc_battery_callback(nrfx_saadc_evt_t const * p_event){}
|
||||
//刺激反馈电压,堵塞模式,不需要事件,定义空的事件回调函数
|
||||
void saadc_stimulate_callback(nrfx_saadc_evt_t const * p_event){}
|
||||
/********************************************************************
|
||||
* name : void battery_adc_init(void)
|
||||
* description : ADC初始化,刺激电压检测、电池电压检测、电极脱落电压检测
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void battery_adc_init(void)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
|
||||
//初始化SAADC,注册事件回调函数。空函数即可
|
||||
err_code = nrf_drv_saadc_init(NULL, saadc_battery_callback);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
//配置通道1,输入引脚为AIN7,电池电压
|
||||
nrf_saadc_channel_config_t channeltwo_config =
|
||||
NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7);
|
||||
|
||||
err_code = nrfx_saadc_channel_init(SAADC_BATTERY_CHANNEL, &channeltwo_config);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
// //配置通道2,输入引脚为AIN4,电极片脱落电压检测
|
||||
// nrf_saadc_channel_config_t channelthree_config =
|
||||
// NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4);
|
||||
|
||||
// //初始化SAADC通道3
|
||||
// err_code = nrfx_saadc_channel_init(SAADC_ELECTRODE_CHANNEL, &channelthree_config);
|
||||
// APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
|
||||
// 如需更高精度非线性计算(示例)
|
||||
float nonlinear_percentage(float voltage) {
|
||||
// 三元锂电池的典型放电曲线拟合多项式
|
||||
float p = (voltage - 3.4f) / 0.8f; // 归一化到[0,1]
|
||||
return 100 * (1.0f - 0.2f*p - 0.8f*p*p);
|
||||
}
|
||||
|
||||
// 锂电池电量计算函数
|
||||
// 输入:当前电压(单位:伏特)
|
||||
// 输出:电量百分比(0~100)
|
||||
int calculate_battery_percentage(float voltage)
|
||||
{
|
||||
// 定义电压范围
|
||||
const float VOLTAGE_MIN = 3.4f; // 0%电量对应电压
|
||||
const float VOLTAGE_MAX = 4.195f; // 100%电量对应电压
|
||||
|
||||
// 边界检查
|
||||
if (voltage <= VOLTAGE_MIN) {
|
||||
return 0;
|
||||
} else if (voltage >= VOLTAGE_MAX) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
// 线性插值计算百分比(可根据实际放电曲线修改算法)
|
||||
float percentage = (voltage - VOLTAGE_MIN) / (VOLTAGE_MAX - VOLTAGE_MIN) * 100.0f;
|
||||
|
||||
// 四舍五入取整
|
||||
return (int)(percentage + 0.5f);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void CalculateBatteryPower(void)
|
||||
* description : 计算电池电量(0-100)
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
|
||||
void CalculateBatteryPower(void)
|
||||
{
|
||||
uint16_t Adctemp;
|
||||
nrf_saadc_value_t Battery_Saadc_Value;
|
||||
//启动一次ADC采样,存在Battery_Saadc_Value中
|
||||
nrfx_saadc_sample_convert(SAADC_BATTERY_CHANNEL, &Battery_Saadc_Value);
|
||||
|
||||
Adctemp = ((Battery_Saadc_Value * 3600) / 16384);
|
||||
|
||||
static float lastBatteryPercentage = 100;
|
||||
int temp = calculate_battery_percentage(Adctemp * 5.12557);
|
||||
|
||||
if(Uncharged == ChargeState) //如果没有处于充电状态,不允许电量上升,只能下降
|
||||
{
|
||||
if(temp < lastBatteryPercentage)
|
||||
Battery_Percentage = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
Battery_Percentage = temp;
|
||||
}
|
||||
lastBatteryPercentage = Battery_Percentage;
|
||||
}
|
||||
|
||||
short short_to_big_endian(short value)
|
||||
{
|
||||
uint8_t buf[2];
|
||||
short resultShort;
|
||||
buf[0] = (value >> 8) & 0xFF; // 高字节(Big-Endian 第一个字节)
|
||||
buf[1] = value & 0xFF; // 低字节(Big-Endian 第二个字节)
|
||||
memcpy(&resultShort,buf,2);
|
||||
return resultShort;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void rms_saadc_callback(nrfx_saadc_evt_t const * p_event)
|
||||
* description : 肌电采集SAADC事件回调函数,只有一个缓存填满后才会进入事件回调函数
|
||||
* Input : nrfx_saadc_evt_t const * p_event:saadc事件
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
|
||||
void rms_saadc_callback(nrfx_saadc_evt_t const * p_event)
|
||||
{
|
||||
static float32_t AdcFilter_g[AD_RAW_MAX] __attribute__((aligned(4)));
|
||||
float32_t outFilter __attribute__((aligned(4)));
|
||||
float32_t vol __attribute__((aligned(4)));
|
||||
static emg_data_t emgData=
|
||||
{
|
||||
.emgCnt = 0
|
||||
};
|
||||
|
||||
if(p_event->type == NRF_DRV_SAADC_EVT_DONE)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_BUFFER_LEN);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
for(int i = 0; i < SAMPLES_BUFFER_LEN; i++)
|
||||
{
|
||||
if(p_event->data.done.p_buffer[i] < 0)
|
||||
vol = 0;
|
||||
else
|
||||
{
|
||||
vol = (p_event->data.done.p_buffer[i]*3600/16384) - 1545; //
|
||||
}
|
||||
bs_bp(&vol, &outFilter); //5.6us
|
||||
if(emgData.emgCnt < AD_RAW_MAX) //防止溢出
|
||||
AdcFilter_g[emgData.emgCnt] = outFilter;
|
||||
|
||||
emgData.emgCnt++;
|
||||
if(emgData.emgCnt >= AD_RAW_MAX)
|
||||
{
|
||||
emgData.emgCnt=0;
|
||||
float32_t temp __attribute__((aligned(4)));
|
||||
arm_rms_f32(AdcFilter_g, AD_RAW_MAX, &temp);//6us
|
||||
|
||||
emgData.EmgValue = temp*0.8806 - 3.028;
|
||||
if(emgData.EmgValue < 0)
|
||||
emgData.EmgValue = 0;
|
||||
// if(temp < 0)
|
||||
// emgData.EmgValue = 0;
|
||||
// else
|
||||
// emgData.EmgValue = 0.6722 * temp + 3.7097;
|
||||
|
||||
uint16_t outfRms;
|
||||
outfRms = (short)emgData.EmgValue;
|
||||
outfRms = short_to_big_endian(outfRms);
|
||||
ble_send_rms_data(outfRms);
|
||||
}
|
||||
|
||||
//ble_send_rms_data(save_value[i]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void timer3_rms_handler(nrf_timer_event_t event_type, void* p_context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void timer3_rms_init(void)
|
||||
* description : 定时器1初始化
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void timer3_rms_init(void)
|
||||
{
|
||||
uint32_t err_code = NRF_SUCCESS;
|
||||
uint32_t time_us = 500; //采样频率2kHz
|
||||
uint32_t time_ticks;
|
||||
nrfx_timer_config_t timer3_cfg = NRFX_TIMER_DEFAULT_CONFIG;
|
||||
err_code = nrfx_timer_init(&TIMER3_RMS, &timer3_cfg, timer3_rms_handler);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
time_ticks = nrfx_timer_us_to_ticks(&TIMER3_RMS, time_us);
|
||||
nrfx_timer_extended_compare(
|
||||
&TIMER3_RMS, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void timer3_rms_start(void)
|
||||
* description : 开启定时器1
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void timer3_rms_start(void)
|
||||
{
|
||||
nrfx_timer_enable(&TIMER3_RMS);
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void timer3_rms_stop(void)
|
||||
* description : 停止定时器1
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void timer3_rms_stop(void)
|
||||
{
|
||||
nrfx_timer_disable(&TIMER3_RMS);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void PPIEegAdcInit(void)
|
||||
* description : ADCPPI通道初始化
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void PPIEegAdcInit(void)
|
||||
{
|
||||
uint32_t err_code = NRF_SUCCESS;
|
||||
|
||||
err_code = nrf_drv_ppi_init();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
//分配PPI通道,PPI通道的分配是由驱动函数完成的,分配的通道号保存到my_ppi_channel1中
|
||||
err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel5);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
//分配PPI通道的EEP和TEP
|
||||
err_code = nrf_drv_ppi_channel_assign(m_ppi_channel5,
|
||||
nrf_drv_timer_event_address_get(&TIMER3_RMS, NRF_TIMER_EVENT_COMPARE0),
|
||||
nrf_drv_saadc_sample_task_get());
|
||||
APP_ERROR_CHECK(err_code);
|
||||
//使能PPI通道
|
||||
err_code = nrf_drv_ppi_channel_enable(m_ppi_channel5);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void rms_saadc_init(void)
|
||||
* description : 肌电采集saadc初始化
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void rms_saadc_init(void)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
nrf_drv_saadc_uninit(); //先反初始化
|
||||
//配置通道0,输入引脚为AIN3,采集信号
|
||||
nrf_saadc_channel_config_t channel_config =
|
||||
NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
|
||||
//初始化SAADC,注册事件回调函数。
|
||||
err_code = nrf_drv_saadc_init(NULL, rms_saadc_callback);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
//初始化SAADC通道0
|
||||
err_code = nrfx_saadc_channel_init(SAADC_RMS_SAMPLE_CHANNEL, &channel_config);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
//配置缓存1,将缓存1地址赋值给SAADC驱动程序中的控制块m_cb的一级缓存指针
|
||||
err_code = nrfx_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_BUFFER_LEN);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
//配置缓存2,将缓存1地址赋值给SAADC驱动程序中的控制块m_cb的二级缓存指针
|
||||
err_code = nrfx_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_BUFFER_LEN);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
|
||||
// 电极脱落检测
|
||||
void ElectFallOff(void)
|
||||
{
|
||||
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void timer4_output_ctrl_handler(nrf_timer_event_t event_type, void* p_context)
|
||||
* description : 变压器电压读取、变压器开关控制、脱落检测、刺激自调节
|
||||
* Input : nrf_timer_event_t event_type:定时器事件类型
|
||||
void* p_context
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void timer1_output_ctrl_handler(nrf_timer_event_t event_type, void* p_context)
|
||||
{
|
||||
switch(event_type)
|
||||
{
|
||||
case NRF_TIMER_EVENT_COMPARE0:
|
||||
//ElectFallOff();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void timer1_output_ctrl_init(void)
|
||||
* description : 输出控制定时器初始化
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void timer1_output_ctrl_init(void)
|
||||
{
|
||||
ret_code_t err_code = NRF_SUCCESS;
|
||||
uint32_t time_us = 50;
|
||||
uint32_t time_ticks;
|
||||
|
||||
nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG;
|
||||
|
||||
err_code = nrfx_timer_init(&TIMER_ADC, &timer_cfg, timer1_output_ctrl_handler);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
//定时时间(单位us)转换为ticks
|
||||
time_ticks = nrfx_timer_us_to_ticks(&TIMER_ADC, time_us);
|
||||
//设置定时器捕获/比较通道及该通道的比较值,使能通道的比较中断
|
||||
nrfx_timer_extended_compare(
|
||||
&TIMER_ADC, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
|
||||
nrfx_timer_enable(&TIMER_ADC);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************** END OF FILE ***************************/
|
||||
817
app/Src/drv_uart.c
Normal file
817
app/Src/drv_uart.c
Normal file
@@ -0,0 +1,817 @@
|
||||
/********************************************************************
|
||||
Copyright (c) 2021 Xiangyu Medical Co.,Ltd. All rights reserved.
|
||||
FileName : drv_uart.c
|
||||
Author : zhangdawei
|
||||
Version : V1.0
|
||||
Date :
|
||||
Note :
|
||||
History :
|
||||
********************************************************************/
|
||||
/* Includes ------------------------------------------------------*/
|
||||
#include "drv_uart.h"
|
||||
#include "pca10040.h"
|
||||
#include "ble_nus.h"
|
||||
#include "time.h"
|
||||
#include "IoControl.h"
|
||||
#include "nrf_drv_timer.h"
|
||||
#include "fds.h"
|
||||
/* Private define ------------------------------------------------*/
|
||||
BLE_NUS_DEF(m_nus); //定义名称为m_nus的串口透传服务实例
|
||||
/* Private typedef -----------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------*/
|
||||
/* 接收到的方案信息 */
|
||||
SchemeData_t SchemeData;
|
||||
SchemeData_t PreStorageSchemeData;// 设备预存信息
|
||||
uint16_t m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - 3; /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
|
||||
/* Private variables ---------------------------------------------*/
|
||||
//该变量用于保存连接句柄,初始值设置为无连接
|
||||
uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
/* 电池电量的原始值 */
|
||||
nrf_saadc_value_t Battery_Saadc_Value = 10000;
|
||||
/* 电池电压百分比 */
|
||||
uint8_t Battery_Percentage = 100;
|
||||
/* 肌电采集定时器初始化标志 */
|
||||
uint8_t TimerEegAdcInit_Flag = 0;
|
||||
/* 控制电流标志 */
|
||||
uint8_t CurrentFlag = 0;
|
||||
/* 设备的连接状态 */
|
||||
ConnectStateInfo_e DeviceConnectState = DisconnectState;
|
||||
ElectrodeStatusInfo_e ElectrodeStatusInfo = ElectrodeConnectted;
|
||||
ElectrodeStatusInfo_e LastElectrodeStatusInfo = ElectrodeConnectted;
|
||||
/* 适配器连接状态 */
|
||||
AdapterStateInfo_e AdapterState = AdapterNotConnected;
|
||||
AdapterStateInfo_e LastAdapterState = AdapterNotConnected;
|
||||
|
||||
/* MAC地址数组 */
|
||||
uint8_t BLE_MAC[BLE_GAP_ADDR_LEN];
|
||||
//定义FDS异步操作标志结构体
|
||||
my_fds_info_t my_fds_info;
|
||||
// 初始化参数信息
|
||||
SchemePara_t SchemePara = {
|
||||
.text = 0
|
||||
};
|
||||
uint16_t ccrvaluebuf[70] = {
|
||||
23,25,27,29,31,33,35,37,39,41, //1-10
|
||||
43,45,47,50,52,54,56,58,60,63, //11-20
|
||||
65,67,69,71,74,76,78,80,82,85, //21-30
|
||||
87,89,91,93,95,97,99,101,103,105, //31-40
|
||||
108,111,114,117,120,123,126,129,132,134, //41-50
|
||||
136,138,140,142,144,146,148,150,152,154, //51-60
|
||||
155,156,158,160,162,164,167,170,172,174 //61-70
|
||||
};
|
||||
#define EEG_DATA_LENGTH ( 50 )
|
||||
uint8_t aEEGData[EEG_DATA_LENGTH] = {
|
||||
23,25,27,29,31,33,35,37,39,41,
|
||||
43,45,47,50,52,54,56,58,60,63,
|
||||
65,67,69,71,74,76,78,80,82,85,
|
||||
87,89,91,93,95,97,99,101,103,105,
|
||||
108,111,114,117,120,123,126,129,132,134
|
||||
};
|
||||
uint8_t eegmode = 0;
|
||||
uint8_t eegflag = 0;
|
||||
|
||||
StimStateInfo_t ChannelStimStateInfo_t;
|
||||
|
||||
rms_data_t rmsData = {.frameHeader = FRAME_HEADER,
|
||||
.frameLength = sizeof(rmsData) - 4, //减去帧头、帧长度、校验和、帧尾
|
||||
.functionCode = D_EMG_DATA_REPORT,
|
||||
.myNumber = 0x01,
|
||||
.channel = 0x01,
|
||||
//.rmsDataBuffer = {0},
|
||||
.checkSum = 0,
|
||||
.frameTail = FRAME_TAIL
|
||||
};
|
||||
|
||||
/* Private function prototypes -----------------------------------*/
|
||||
void StatusInquiry(ElectrodeStatusInfo_e Electrodestatus);
|
||||
void StartStopCtrl(uint8_t StartStopValue);
|
||||
void MACQuery(void);
|
||||
/* Public constants ----------------------------------------------*/
|
||||
/* Public variables ----------------------------------------------*/
|
||||
/********************************************************************
|
||||
* name : void SetFreqWidth(uint8_t* AnalysisDataBffer_t)
|
||||
* description : 设置脉冲频率
|
||||
* Input : AnalysisDataBffer_t:接收到的数据缓冲区
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void SetFreqWidth(uint8_t* AnalysisDataBffer_t)
|
||||
{
|
||||
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void SetRampTime(uint8_t* AnalysisDataBfferIn_t)
|
||||
* description : 设置斜坡时间
|
||||
* Input : AnalysisDataBffer_t:接收到的数据缓冲区
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void SetRampTime(uint8_t* AnalysisDataBffer_t)
|
||||
{
|
||||
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void SetStimPara(uint8_t* AnalysisDataBfferIn_t)
|
||||
* description : 设置刺激参数
|
||||
* Input : AnalysisDataBffer_t:接收到的数据缓冲区
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void SetStimPara(uint8_t* AnalysisDataBffer_t)
|
||||
{
|
||||
|
||||
|
||||
//开启采集模式
|
||||
if(1 == AnalysisDataBffer_t[4])
|
||||
{
|
||||
eegmode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
/********************************************************************
|
||||
* name : static void nus_data_handler(ble_nus_evt_t * p_evt)
|
||||
* description : BLE串口透传事件回调函数
|
||||
* Input : ble_nus_evt_t * p_evt:发生的事件
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
static void nus_data_handler(ble_nus_evt_t * p_evt)
|
||||
{
|
||||
uint8_t FrameLength = 0;//帧长度
|
||||
uint8_t FunctionCode = 0;//功能码
|
||||
uint8_t CheckSum = 0;//校验和
|
||||
uint8_t Sum = 0;//数据和
|
||||
uint8_t SumCCR = 0;//CCR值
|
||||
#define RX_BLE_DATA_LEN 100
|
||||
uint8_t RecieveData[RX_BLE_DATA_LEN] = {0}; //接收数据帧的数组
|
||||
|
||||
if(p_evt->type == BLE_NUS_EVT_RX_DATA)
|
||||
{
|
||||
uint16_t Length = 0;
|
||||
|
||||
Length = p_evt->params.rx_data.length;
|
||||
if(Length > RX_BLE_DATA_LEN)
|
||||
{
|
||||
NRF_LOG_ERROR("RecieveData length error");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(RecieveData, p_evt->params.rx_data.p_data, Length);
|
||||
}
|
||||
|
||||
/* 解析蓝牙收到的数据 */
|
||||
if(0xAA == RecieveData[0])
|
||||
{
|
||||
FrameLength = RecieveData[1]; //帧长度
|
||||
if(FrameLength > (RX_BLE_DATA_LEN - 4))
|
||||
{
|
||||
NRF_LOG_ERROR("RecieveData length error %d", FrameLength);
|
||||
return;
|
||||
}
|
||||
else if(0x55 != RecieveData[FrameLength + 3]) //查找帧尾
|
||||
{
|
||||
NRF_LOG_ERROR("RecieveData end flag error");
|
||||
return;
|
||||
}
|
||||
CheckSum = RecieveData[FrameLength + 2]; //校验和
|
||||
//if(0x55 == RecieveData[FrameLength + 3]) //查找帧尾
|
||||
{
|
||||
/*校验数据包*/
|
||||
for(uint8_t i = 0; i < FrameLength; i++)
|
||||
{
|
||||
Sum += RecieveData[i+2];
|
||||
}
|
||||
SumCCR = Sum & 0xff;
|
||||
|
||||
if(CheckSum == SumCCR)
|
||||
{
|
||||
FunctionCode = RecieveData[2];
|
||||
|
||||
/*模式、脉宽、频率、斜坡时间设置*/
|
||||
if(STIM_PARA_CONTROL == FunctionCode)
|
||||
{
|
||||
SetStimPara(RecieveData); //设置参数
|
||||
ble_nus_data_send(&m_nus, RecieveData, &Length, m_conn_handle);//将收到的数据回复回去
|
||||
}
|
||||
/*电流控制 (控制刺激强度)*/
|
||||
else if(CURRENT_CONTROL == FunctionCode)
|
||||
{
|
||||
NRF_LOG_INFO("CURRENT_CONTROL");
|
||||
|
||||
// SetStandardCurrent(RecieveData); //设置电流
|
||||
// CurrentFlag = 1; //设置电流的标志,此标志为1时表示可以输出电流
|
||||
ble_nus_data_send(&m_nus, RecieveData, &Length, m_conn_handle);//将收到的数据回复回去
|
||||
}
|
||||
/*刺激启停控制*/
|
||||
else if(START_STOP_CONTROL == FunctionCode)
|
||||
{
|
||||
NRF_LOG_INFO("START_STOP_CONTROL");
|
||||
// CurrentFlag = 0; //此标志清0,此时开启电流的标志由通道模式和通道状态控制
|
||||
uint8_t StartStopValue = CH_STOP; //初始状态为停止
|
||||
StartStopValue = RecieveData[StartStopOffset]; //设置启停状态
|
||||
StartStopCtrl(StartStopValue); //启停控制
|
||||
ble_nus_data_send(&m_nus, RecieveData, &Length, m_conn_handle);//将收到的数据回复回去
|
||||
}
|
||||
/*触发采集开始*/
|
||||
else if(TRIG_COLLECT_START_CONTROL == FunctionCode)
|
||||
{
|
||||
NRF_LOG_INFO("TRIG_COLLECT_START_CONTROL");
|
||||
ble_nus_data_send(&m_nus, RecieveData, &Length, m_conn_handle);//将收到的数据回复回去
|
||||
}
|
||||
/*触发刺激开始*/
|
||||
else if(TRIG_STIM_START_CONTROL == FunctionCode)
|
||||
{
|
||||
NRF_LOG_INFO("TRIG_STIM_START_CONTROL");
|
||||
ble_nus_data_send(&m_nus, RecieveData, &Length, m_conn_handle);//将收到的数据回复回去
|
||||
}
|
||||
/*轮询0x8A*/
|
||||
else if(STATUS_INQUIRY == FunctionCode)
|
||||
{
|
||||
StatusInquiry(ElectrodeStatusInfo);
|
||||
NRF_LOG_INFO("STATUS_INQUIRY");
|
||||
}
|
||||
/* 运行轮询 */
|
||||
else if(RUN_ROLL == FunctionCode)
|
||||
{
|
||||
RunRoll();
|
||||
NRF_LOG_INFO("RUN_ROLL");
|
||||
}
|
||||
/* 版本查询 */
|
||||
else if(VERSION_INQUIRY == FunctionCode)
|
||||
{
|
||||
CheckVersion();
|
||||
NRF_LOG_INFO("VERSION_INQUIRY");
|
||||
}
|
||||
else if(SCHEME_QUERY == FunctionCode)
|
||||
{
|
||||
//SchemeQuery();
|
||||
my_fds_info.read = true;
|
||||
NRF_LOG_INFO("SCHEME_QUERY");
|
||||
}
|
||||
else if(MAC_QUERY == FunctionCode)
|
||||
{
|
||||
MACQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/***********end***********/
|
||||
}
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void service_nus_init(void)
|
||||
* description : 串口透传服务初始化
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void service_nus_init(void)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
ble_nus_init_t nus_init; //定义串口透传初始化结构体
|
||||
/*------------------以下代码初始化串口透传服务-------------*/
|
||||
memset(&nus_init, 0, sizeof(nus_init)); //清零串口透传服务初始化结构体
|
||||
nus_init.data_handler = nus_data_handler; //设置串口透传事件回调函数
|
||||
err_code = ble_nus_init(&m_nus, &nus_init); //初始化串口透传服务
|
||||
APP_ERROR_CHECK(err_code);
|
||||
/*------------------初始化串口透传服务-END-----------------*/
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void StartStopCtrl(uint8_t ucStartStopValueIn)
|
||||
* description : 启、停控制处理函数
|
||||
* Input : ucStartStopValueIn:启、停控制值
|
||||
ucChannelIn:通道号
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void StartStopCtrl(uint8_t StartStopValue)
|
||||
{
|
||||
switch(StartStopValue)
|
||||
{
|
||||
case CH_START: StartManage();
|
||||
break;
|
||||
case CH_PAUSE: PauseManage();
|
||||
break;
|
||||
case CH_CONTINUE: RecoverManage();
|
||||
break;
|
||||
case CH_STOP: StopManage();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void StartManage(void)
|
||||
* description : 开始处理函数
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void StartManage(void)
|
||||
{
|
||||
if(eegmode == 1)
|
||||
{
|
||||
eegflag = 1;
|
||||
}
|
||||
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void PauseManage(void)
|
||||
* description : 暂停处理函数
|
||||
* Input : Channel:通道号
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void PauseManage(void)
|
||||
{
|
||||
if(eegmode == 1)
|
||||
{
|
||||
eegflag = 0;
|
||||
}
|
||||
// CHAChannelState_e = IdleState; //设置状态为空闲态,空闲状态下pwm_flag置0
|
||||
// ChannelStimStateInfo_t.ChannelWorkState = Pause;
|
||||
// PwmDACStop();
|
||||
// CloseOutput(); //关闭输出
|
||||
// NRF_LOG_INFO("Pause_Stim");
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void CloseOutput(void)
|
||||
* description : 将输出电流置0,斜坡时间置0,关闭输出PWM
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void CloseOutput(void)
|
||||
{
|
||||
if(eegmode == 1)
|
||||
{
|
||||
eegmode = 0;
|
||||
eegflag = 0;
|
||||
}
|
||||
//ChannelStimStateInfo_t.ucCurrent = 0;
|
||||
// ChannelStimStateInfo_t.Ramp_e = RampIdle;//斜坡状态为空闲态
|
||||
// RampTime = 0; //斜坡时间清0
|
||||
// SetCurrent(0); //设置输出电流为0
|
||||
// PwmSubtractStop(); //关闭输出PWM
|
||||
// PwmDACStop(); //停止充能PWM
|
||||
//// GpioteInit();
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void RecoverManage(void)
|
||||
* description : 继续处理函数
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void RecoverManage(void)
|
||||
{
|
||||
if(eegmode == 1)
|
||||
{
|
||||
eegflag = 1;
|
||||
}
|
||||
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void StopManage(void)
|
||||
* description : 停止处理函数
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void StopManage(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void SetStandardCurrent(uint8_t* AnalysisDataBfferIn_t)
|
||||
* description : 设置标称电流值
|
||||
* Input : AnalysisDataBfferIn_t:接收到的数据缓冲区
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void SetStandardCurrent(uint8_t* AnalysisDataBffer_t)
|
||||
{
|
||||
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void StatusInquiry(void)
|
||||
* description : 状态轮询
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void StatusInquiry(ElectrodeStatusInfo_e Electrodestatus)
|
||||
{
|
||||
uint8_t j = 2;
|
||||
static uint8_t aTxBuffer[10] = {0};
|
||||
uint32_t ulCrc = 0;
|
||||
uint16_t Length = 10;
|
||||
|
||||
/* 帧头、帧尾*/
|
||||
aTxBuffer[HeadOffset] = 0xAA;
|
||||
aTxBuffer[DataLengthOffset] = 0x06;
|
||||
aTxBuffer[FunctionCodeOffset] = STATUS_INQUIRY;
|
||||
aTxBuffer[ChannelNumOffset] = 0x00;
|
||||
aTxBuffer[ElectrodeStatusOffset] = 0x01;
|
||||
aTxBuffer[StimStatusOffset] = ChannelStimStateInfo_t.Ramp_e;
|
||||
aTxBuffer[StimCurrentOffset] = ChannelStimStateInfo_t.ucCurrent;
|
||||
aTxBuffer[ResetOffset] = 0x00;
|
||||
aTxBuffer[TailOffset] = 0x55;
|
||||
|
||||
/* 校验和 */
|
||||
for(uint8_t i = 0; i < 6; i++)
|
||||
{
|
||||
ulCrc += aTxBuffer[j];
|
||||
j++;
|
||||
}
|
||||
aTxBuffer[DataCrcOffset] = (uint8_t)ulCrc;
|
||||
|
||||
ble_nus_data_send(&m_nus, aTxBuffer, &Length, m_conn_handle);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : uint8_t caculate_sum_check(void)
|
||||
* description : 运行校验和计算
|
||||
* Input : typeStructHeader:数据结构头部
|
||||
typeStructLength:数据结构长度
|
||||
* Output : void
|
||||
* Return : 计算结果
|
||||
********************************************************************/
|
||||
|
||||
uint8_t caculate_sum_check(uint8_t *typeStructHeader, uint8_t typeStructLength)
|
||||
{
|
||||
uint8_t sum = 0;
|
||||
uint8_t * typeStructCMD = &typeStructHeader[2];
|
||||
for (uint8_t i = 0; i < typeStructLength; i++)
|
||||
{
|
||||
sum += typeStructCMD[i];
|
||||
}
|
||||
return sum&0xFF;
|
||||
}
|
||||
|
||||
/// @brief 运行状态回复
|
||||
reply_run_status_t replyRunStatus = {
|
||||
.frameHeader = FRAME_HEADER,
|
||||
.frameLength = sizeof(replyRunStatus) - 4, //减去帧头、帧长度、校验和、帧尾
|
||||
.functionCode = RUN_ROLL,
|
||||
.myNumber = 0x01,
|
||||
.channel = 0x01,
|
||||
.checkSum = 0,
|
||||
.frameTail = FRAME_TAIL
|
||||
};
|
||||
/********************************************************************
|
||||
* name : void RunRoll(void)
|
||||
* description : 运行轮询
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void RunRoll(void)
|
||||
{
|
||||
uint32_t ulCrc = 0;
|
||||
uint16_t Length = sizeof(replyRunStatus);
|
||||
|
||||
replyRunStatus.ChargeState = ChargeState;
|
||||
replyRunStatus.BatteryLevelA = Battery_Percentage;
|
||||
|
||||
replyRunStatus.checkSum = (uint8_t)caculate_sum_check((uint8_t *)&replyRunStatus, replyRunStatus.frameLength);
|
||||
|
||||
ble_nus_data_send(&m_nus, &replyRunStatus.frameHeader, &Length, m_conn_handle);
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void CheckVersion(void)
|
||||
* description : 版本查询
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
check_version_t checkVersion = {
|
||||
.frameHeader = FRAME_HEADER,
|
||||
.frameLength = sizeof(checkVersion) - 4, //减去帧头、帧长度、校验和、帧尾
|
||||
.functionCode = VERSION_INQUIRY,
|
||||
.myNumber = 0x01,
|
||||
.channel = 0x01,
|
||||
.checkSum = 0,
|
||||
.frameTail = FRAME_TAIL
|
||||
}
|
||||
void CheckVersion(void)
|
||||
{
|
||||
uint8_t j = 2;
|
||||
static uint8_t aTxBuffer[21] = {0};
|
||||
uint32_t ulCrc = 0;
|
||||
uint16_t Length = 21;
|
||||
|
||||
/* 帧头、帧尾*/
|
||||
aTxBuffer[HeadOffset] = 0xAA;
|
||||
aTxBuffer[DataLengthOffset] = 0x11;
|
||||
aTxBuffer[FunctionCodeOffset] = VERSION_INQUIRY;
|
||||
aTxBuffer[ChannelNumOffset] = 0x00;
|
||||
aTxBuffer[20] = 0x55;
|
||||
|
||||
/* 协议中规定先发送高字节,后发送低字节 */
|
||||
aTxBuffer[4] = VersionDes[0];
|
||||
aTxBuffer[5] = VersionDes[1];
|
||||
aTxBuffer[6] = VersionDes[2];
|
||||
aTxBuffer[7] = VersionDes[3];
|
||||
aTxBuffer[8] = VersionDes[4];
|
||||
aTxBuffer[9] = VersionDes[5];
|
||||
aTxBuffer[10] = VersionDes[6];
|
||||
aTxBuffer[11] = VersionDes[7];
|
||||
aTxBuffer[12] = 0x00;
|
||||
aTxBuffer[13] = 0x00;
|
||||
aTxBuffer[14] = 0x00;
|
||||
aTxBuffer[15] = 0x00;
|
||||
aTxBuffer[16] = 0x00;
|
||||
aTxBuffer[17] = 0x00;
|
||||
aTxBuffer[18] = 0x00;
|
||||
/* 校验和 */
|
||||
for(uint8_t i = 0; i < 17; i++)
|
||||
{
|
||||
ulCrc += aTxBuffer[j];
|
||||
j++;
|
||||
}
|
||||
aTxBuffer[19] = (uint8_t)ulCrc;
|
||||
ble_nus_data_send(&m_nus, aTxBuffer, &Length, m_conn_handle);
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void EegDataSend(void)
|
||||
* description : 发送肌电数据
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void EegDataSend(void)
|
||||
{
|
||||
uint8_t j = 2;
|
||||
|
||||
static uint8_t aTxBuffer[EEG_DATA_LENGTH+6] = {0};
|
||||
uint32_t ulCrc = 0;
|
||||
uint16_t Length = EEG_DATA_LENGTH+6;
|
||||
ret_code_t err_code;
|
||||
|
||||
/* 帧头、帧尾*/
|
||||
aTxBuffer[HeadOffset] = 0xAA;
|
||||
aTxBuffer[DataLengthOffset] = 0x34;
|
||||
aTxBuffer[FunctionCodeOffset] = EEG_DATA;
|
||||
aTxBuffer[ChannelNumOffset] = 0x00;
|
||||
aTxBuffer[EEG_DATA_LENGTH+5] = 0x55;
|
||||
|
||||
/* 协议中规定先发送高字节,后发送低字节 */
|
||||
memcpy(&aTxBuffer[4],aEEGData,EEG_DATA_LENGTH);
|
||||
|
||||
/* 校验和 */
|
||||
for(uint8_t i = 0; i < EEG_DATA_LENGTH+2; i++)
|
||||
{
|
||||
ulCrc += aTxBuffer[j];
|
||||
j++;
|
||||
}
|
||||
aTxBuffer[EEG_DATA_LENGTH+4] = (uint8_t)ulCrc;
|
||||
ble_nus_data_send(&m_nus, aTxBuffer, &Length, m_conn_handle);
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void UpdateCurrent(uint8_t CurrentSend)
|
||||
* description : 同步电流
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void UpdateCurrent(uint8_t CurrentSend)
|
||||
{
|
||||
uint8_t j = 2;
|
||||
uint8_t aTxBuffer[8] = {0};
|
||||
uint32_t ulCrc = 0;
|
||||
uint16_t Length = 8;
|
||||
|
||||
/* 帧头、帧尾*/
|
||||
aTxBuffer[HeadOffset] = 0xAA;
|
||||
aTxBuffer[DataLengthOffset] = 0x04;
|
||||
aTxBuffer[FunctionCodeOffset] = CURRENT_CONTROL;
|
||||
aTxBuffer[ChannelNumOffset] = 0x00;
|
||||
aTxBuffer[7] = 0x55;
|
||||
|
||||
/* 协议中规定先发送高字节,后发送低字节 */
|
||||
aTxBuffer[4] = CurrentSend;
|
||||
aTxBuffer[5] = 0x01; // 01代表蓝牙设备发送
|
||||
|
||||
/* 校验和 */
|
||||
for(uint8_t i = 0; i < 4; i++)
|
||||
{
|
||||
ulCrc += aTxBuffer[j];
|
||||
j++;
|
||||
}
|
||||
aTxBuffer[6] = (uint8_t)ulCrc;
|
||||
ble_nus_data_send(&m_nus, aTxBuffer, &Length, m_conn_handle);
|
||||
}
|
||||
|
||||
|
||||
void user_ble_or_uart_send(char * txBufferP, uint16_t Length)
|
||||
{
|
||||
ble_nus_data_send(&m_nus, txBufferP, &Length, m_conn_handle);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void ble_send_rms_data(uint16_t rms_data)
|
||||
* description : 发送肌电数据到主机
|
||||
* Input : uint16_t rms_data:肌电数据
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void ble_send_rms_data(uint16_t rms_data)
|
||||
{
|
||||
uint32_t TempSum = 0;
|
||||
|
||||
static uint8_t sendCnt = 0;
|
||||
|
||||
if(sendCnt < RMS_USER_DATA_LENGTH)
|
||||
{
|
||||
rmsData.rmsDataBuffer[sendCnt] = rms_data; //将rms_data存入rmsData的rmsDataBuffer数组中
|
||||
sendCnt++;
|
||||
if(sendCnt < RMS_USER_DATA_LENGTH)
|
||||
return ; //如果发送次数小于RMS_USER_DATA_LENGTH,则不发送
|
||||
}
|
||||
sendCnt = 0; //发送次数达到RMS_USER_DATA_LENGTH后,重置发送次数
|
||||
rmsData.myNumber = 1;
|
||||
//rmsData.myNumber++;
|
||||
uint8_t * sumCheckStartP = (uint8_t *)&rmsData.functionCode;
|
||||
for(uint8_t i = 0; i < rmsData.frameLength; i++)
|
||||
{
|
||||
TempSum += sumCheckStartP[i];
|
||||
}
|
||||
rmsData.checkSum = TempSum & 0xff;
|
||||
user_ble_or_uart_send((uint8_t *)&rmsData, sizeof(rmsData)); //145us
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* name : void StateUpLoad(AdapterStateInfo_e AdapterStateTemp , ElectrodeStatusInfo_e ElectrodeStatusTemp)
|
||||
* description : 电极片和适配器状态上传
|
||||
* Input : AdapterStateInfo_e AdapterStateTemp , ElectrodeStatusInfo_e ElectrodeStatusTemp
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void StateUpLoad(AdapterStateInfo_e AdapterStateTemp , ElectrodeStatusInfo_e ElectrodeStatusTemp)
|
||||
{
|
||||
uint8_t j = 2;
|
||||
uint8_t aTxBuffer[8] = {0};
|
||||
uint32_t ulCrc = 0;
|
||||
uint16_t Length = 8;
|
||||
|
||||
AdapterStateInfo_e AdapterStateIn;
|
||||
ElectrodeStatusInfo_e ElectrodeStatusIn;
|
||||
|
||||
AdapterStateIn = AdapterStateTemp;
|
||||
ElectrodeStatusIn = ElectrodeStatusTemp;
|
||||
|
||||
/* 帧头、帧尾*/
|
||||
aTxBuffer[HeadOffset] = 0xAA;
|
||||
aTxBuffer[DataLengthOffset] = 0x04;
|
||||
aTxBuffer[FunctionCodeOffset] = STATE_UPLOAD;
|
||||
aTxBuffer[ChannelNumOffset] = 0x00;
|
||||
aTxBuffer[7] = 0x55;
|
||||
|
||||
aTxBuffer[4] = AdapterStateIn; // 适配器连接状态
|
||||
aTxBuffer[5] = ElectrodeStatusIn; // 电极片状态
|
||||
|
||||
if(ElectrodeStatusIn == ElectrodeFalloff)
|
||||
{
|
||||
|
||||
ElectrodeStatusInfo = ElectrodeConnectted;
|
||||
}
|
||||
|
||||
NRF_LOG_INFO("Electrodestatus = %d",ElectrodeStatusIn);
|
||||
/* 校验和 */
|
||||
for(uint8_t i = 0; i < 4; i++)
|
||||
{
|
||||
ulCrc += aTxBuffer[j];
|
||||
j++;
|
||||
}
|
||||
aTxBuffer[6] = (uint8_t)ulCrc;
|
||||
ble_nus_data_send(&m_nus, aTxBuffer, &Length, m_conn_handle);
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void UpdateControlStatus(uint8_t ControlStatus)
|
||||
* description : 同步电流
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void UpdateControlStatus(uint8_t ControlStatus)
|
||||
{
|
||||
uint8_t j = 2;
|
||||
uint8_t aTxBuffer[8] = {0};
|
||||
uint32_t ulCrc = 0;
|
||||
uint16_t Length = 8;
|
||||
|
||||
/* 帧头、帧尾*/
|
||||
aTxBuffer[HeadOffset] = 0xAA;
|
||||
aTxBuffer[DataLengthOffset] = 0x04;
|
||||
aTxBuffer[FunctionCodeOffset] = START_STOP_CONTROL;
|
||||
aTxBuffer[ChannelNumOffset] = 0x00;
|
||||
aTxBuffer[7] = 0x55;
|
||||
|
||||
/* 协议中规定先发送高字节,后发送低字节 */
|
||||
aTxBuffer[4] = ControlStatus;
|
||||
aTxBuffer[5] = 0x01; // 01代表蓝牙设备发送
|
||||
|
||||
/* 校验和 */
|
||||
for(uint8_t i = 0; i < 4; i++)
|
||||
{
|
||||
ulCrc += aTxBuffer[j];
|
||||
j++;
|
||||
}
|
||||
aTxBuffer[6] = (uint8_t)ulCrc;
|
||||
ble_nus_data_send(&m_nus, aTxBuffer, &Length, m_conn_handle);
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void SchemeQuery(uint8_t idMSB,uint8_t idLSB)
|
||||
* description : 方案查询
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void SchemeQuery(uint8_t idMSB,uint8_t idLSB)
|
||||
{
|
||||
uint8_t j = 2;
|
||||
static uint8_t aTxBuffer[8] = {0};
|
||||
uint32_t ulCrc = 0;
|
||||
uint16_t Length = 8;
|
||||
|
||||
/* 帧头、帧尾*/
|
||||
aTxBuffer[HeadOffset] = 0xAA;
|
||||
aTxBuffer[DataLengthOffset] = 0x04;
|
||||
aTxBuffer[FunctionCodeOffset] = SCHEME_QUERY;
|
||||
aTxBuffer[ChannelNumOffset] = 0x00;
|
||||
aTxBuffer[7] = 0x55;
|
||||
|
||||
/* 协议中规定先发送高字节,后发送低字节 */
|
||||
aTxBuffer[4] = idMSB;
|
||||
aTxBuffer[5] = idLSB;
|
||||
|
||||
/* 校验和 */
|
||||
for(uint8_t i = 0; i < 4; i++)
|
||||
{
|
||||
ulCrc += aTxBuffer[j];
|
||||
j++;
|
||||
}
|
||||
aTxBuffer[6] = (uint8_t)ulCrc;
|
||||
ble_nus_data_send(&m_nus, aTxBuffer, &Length, m_conn_handle);
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void MACQuery(void)
|
||||
* description : MAC地址查询
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void MACQuery(void)
|
||||
{
|
||||
uint8_t j = 2;
|
||||
static uint8_t aTxBuffer[12] = {0};
|
||||
uint32_t ulCrc = 0;
|
||||
uint16_t Length = 12;
|
||||
|
||||
/* 帧头、帧尾*/
|
||||
aTxBuffer[HeadOffset] = 0xAA;
|
||||
aTxBuffer[DataLengthOffset] = 0x08;
|
||||
aTxBuffer[FunctionCodeOffset] = MAC_QUERY;
|
||||
aTxBuffer[ChannelNumOffset] = 0x00;
|
||||
aTxBuffer[11] = 0x55;
|
||||
|
||||
aTxBuffer[4] = BLE_MAC[5];
|
||||
aTxBuffer[5] = BLE_MAC[4];
|
||||
aTxBuffer[6] = BLE_MAC[3];
|
||||
aTxBuffer[7] = BLE_MAC[2];
|
||||
aTxBuffer[8] = BLE_MAC[1];
|
||||
aTxBuffer[9] = BLE_MAC[0];
|
||||
/* 校验和 */
|
||||
for(uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
ulCrc += aTxBuffer[j];
|
||||
j++;
|
||||
}
|
||||
aTxBuffer[10] = (uint8_t)ulCrc;
|
||||
ble_nus_data_send(&m_nus, aTxBuffer, &Length, m_conn_handle);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void JudgeLedMode(void)
|
||||
* description :
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return : void
|
||||
********************************************************************/
|
||||
void JudgeLedMode(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DisconnectControl(void)
|
||||
{
|
||||
StopManage();
|
||||
}
|
||||
|
||||
/*************************** END OF FILE ***************************/
|
||||
|
||||
|
||||
482
app/Src/timer.c
Normal file
482
app/Src/timer.c
Normal file
@@ -0,0 +1,482 @@
|
||||
/********************************************************************
|
||||
Copyright (c) 2021 Xiangyu Medical Co.,Ltd. All rights reserved.
|
||||
FileName : timer.c
|
||||
Author : zhangdawei
|
||||
Version : V1.0
|
||||
Date :
|
||||
Note :
|
||||
History :
|
||||
********************************************************************/
|
||||
/* Includes ------------------------------------------------------*/
|
||||
#include "nrf_drv_pwm.h"
|
||||
#include "drv_uart.h"
|
||||
#include "IoControl.h"
|
||||
#include "timer.h"
|
||||
#include "nrf_delay.h"
|
||||
#include "nrf_drv_ppi.h"
|
||||
#include "nrf_drv_gpiote.h"
|
||||
/* Private define ------------------------------------------------*/
|
||||
/* 定义APP定时器 */
|
||||
APP_TIMER_DEF(detect_button_100ms);
|
||||
#define DETECT_BUTTON APP_TIMER_TICKS(100)
|
||||
|
||||
|
||||
/* Private typedef -----------------------------------------------*/
|
||||
//定义名称为m_pwm_add的驱动程序实例
|
||||
static nrfx_pwm_t m_pwm_dac = NRFX_PWM_INSTANCE(1);
|
||||
static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(0);
|
||||
static nrfx_pwm_t m_pwm2 = NRFX_PWM_INSTANCE(2);
|
||||
/* Private constants ---------------------------------------------*/
|
||||
|
||||
/* Private variables ---------------------------------------------*/
|
||||
|
||||
/* 呼吸灯占空比 */
|
||||
uint16_t m_step = 150;
|
||||
/* 存放RunLED占空比的数组 */
|
||||
static nrf_pwm_values_common_t seq3_values[M_STEP*2];
|
||||
//定义PWM序列,该序列必须位于RAM中,因此要定义为static类型
|
||||
static nrf_pwm_values_common_t dac_values[] = {CYCLE_CALUE}; //14
|
||||
|
||||
static nrf_pwm_values_wave_form_t seq0_current_values[] =
|
||||
{
|
||||
10000 - 600,
|
||||
10000 - 400,
|
||||
10000 - 200,
|
||||
10000 //100Hz
|
||||
};
|
||||
|
||||
|
||||
static nrf_pwm_values_wave_form_t seq2_current_values[] =
|
||||
{
|
||||
800 - 125,
|
||||
800,
|
||||
800,
|
||||
800 //20khz
|
||||
};
|
||||
|
||||
E_WORK_STATE eRmsState = E_RMS_STOP;
|
||||
|
||||
/* Private function prototypes -----------------------------------*/
|
||||
|
||||
/* Public constants ----------------------------------------------*/
|
||||
/* Public variables ----------------------------------------------*/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* name : void acquisition_start(void)
|
||||
* description : 开始采集肌电
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void acquisition_start(void)
|
||||
{
|
||||
eRmsState = E_RMS_START;
|
||||
// rms_saadc_init();
|
||||
nrf_gpio_pin_set(SAMPLE_POWER_PIN);
|
||||
open_acquisition_relay();
|
||||
|
||||
timer3_rms_start();
|
||||
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void acquisition_stop(void)
|
||||
* description : 停止肌电采集
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void acquisition_stop(void)
|
||||
{
|
||||
timer3_rms_stop();
|
||||
eRmsState = E_RMS_STOP;
|
||||
nrf_gpio_pin_clear(SAMPLE_POWER_PIN);
|
||||
close_acquisition_relay();
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void stimulate_start(void)
|
||||
* description : 开始刺激
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void stimulate_start(void)
|
||||
{
|
||||
acquisition_stop(); //先停止肌电采集
|
||||
// stimulate_stop(); //停止刺激,重新开始刺激
|
||||
|
||||
eRmsState = E_STIM_START;
|
||||
open_stimulate_relay();
|
||||
pwm0_play();
|
||||
pwm2_play();
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void stimulate_stop(void)
|
||||
* description : 停止刺激
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void stimulate_stop(void)
|
||||
{
|
||||
eRmsState = E_STIM_STOP;
|
||||
close_stimulate_relay();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* name : static void detect_button(void)
|
||||
* description : 开关机按键检测处理
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
static void detect_button(void)
|
||||
{
|
||||
static uint8_t CountValue=0;
|
||||
if((Bit_RESET == nrf_gpio_pin_read(KEY_PWR_SWITICH))&&((ChargeState == Uncharged))) //检测按键是否按下
|
||||
{
|
||||
CountValue++;
|
||||
|
||||
if(CountValue == 10)
|
||||
{
|
||||
if(POWER_CLOSE == DeviceState) //开机
|
||||
{
|
||||
DeviceState = POWER_OPEN;
|
||||
nrf_gpio_pin_set(KEY_POWER); //锁定电源键,给MCU供电
|
||||
|
||||
NRF_LOG_INFO("Open!");
|
||||
StartAdv();
|
||||
}
|
||||
else if(POWER_OPEN == DeviceState) //关机
|
||||
{
|
||||
DeviceState = POWER_CLOSE;
|
||||
acquisition_stop();
|
||||
NRF_LOG_INFO("Close!");
|
||||
nrf_gpio_pin_clear(KEY_POWER); //断电
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CountValue = 0;
|
||||
}
|
||||
static uint16_t runBlinkCount = 0;
|
||||
|
||||
if(runBlinkCount == 0 && DeviceState == POWER_OPEN)
|
||||
nrf_gpio_pin_set(LED_YELLOW);
|
||||
else if(runBlinkCount == 1)
|
||||
nrf_gpio_pin_clear(LED_YELLOW);
|
||||
|
||||
if(runBlinkCount++ > 8) //1S闪烁一次
|
||||
{
|
||||
runBlinkCount = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : static void detect_charging_status(void)
|
||||
* description : 充电状态检测处理
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
static void detect_charging_status(void)
|
||||
{
|
||||
static uint8_t CountValue=0;
|
||||
if((Bit_RESET == nrf_gpio_pin_read(CHG_MANAGER_CHG))) //检测按键是否按下
|
||||
{
|
||||
ChargeState = Charging;
|
||||
}
|
||||
else
|
||||
{
|
||||
ChargeState = Uncharged;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : static void Hundredms_handler(void * p_context)
|
||||
* description : 检测按键是否长按函数,100ms中断一次,累计计数
|
||||
* Input : void *p_context
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
static void Hundredms_handler(void * p_context)
|
||||
{
|
||||
//防止编译器警告,同时清晰地的表明p_context未使用,而不是应用程序忽略了。如果应用
|
||||
//程序需要使用p_context,则不需要这行代码
|
||||
UNUSED_PARAMETER(p_context);
|
||||
/* 开机按键检测处理 */
|
||||
detect_button();
|
||||
/* 电池电量检测 */
|
||||
CalculateBatteryPower();
|
||||
/* 充电状态检测 */
|
||||
detect_charging_status();
|
||||
static uint16_t delay_open = 0;
|
||||
if(POWER_OPEN == DeviceState && delay_open != 70 && delay_open++ >60 )
|
||||
{
|
||||
//acquisition_start();
|
||||
stimulate_start();
|
||||
delay_open = 70;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* name : void AppTimersInit(void)
|
||||
* description : 初始化APP定时器模块、创建APP定时器
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void AppTimersInit(void)
|
||||
{
|
||||
|
||||
ret_code_t err_code = app_timer_init();//初始化APP定时器模块
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
err_code = app_timer_create(&detect_button_100ms,
|
||||
APP_TIMER_MODE_REPEATED,
|
||||
Hundredms_handler);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void ApplicationTimersStart(void)
|
||||
* description : 启动已经创建的的APP定时器
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void ApplicationTimersStart(void)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
|
||||
err_code = app_timer_start(detect_button_100ms, DETECT_BUTTON, NULL);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
/********************************************************************
|
||||
* name : void PwmDACInit(void)
|
||||
* description : 控制DAC的pwm初始化
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void PwmDACInit(void)
|
||||
{
|
||||
//定义PWM初始化配置结构体并初始化参数
|
||||
nrfx_pwm_config_t const config0 =
|
||||
{
|
||||
.output_pins =
|
||||
{
|
||||
PWM_DAC_GPIO, //通道0映射到P WM_DAC_GPIO,空闲状态输出低电平
|
||||
NRFX_PWM_PIN_NOT_USED , //通道1不使用
|
||||
NRFX_PWM_PIN_NOT_USED , //通道2不使用
|
||||
NRFX_PWM_PIN_NOT_USED //通道3不使用
|
||||
},
|
||||
.irq_priority = APP_IRQ_PRIORITY_LOWEST,//中断优先级
|
||||
.base_clock = NRF_PWM_CLK_1MHz, //PWM时钟频率设置为1MHz
|
||||
.count_mode = NRF_PWM_MODE_UP, //向上计数模式
|
||||
.top_value = CYCLE_CALUE, //该值为周期值
|
||||
.load_mode = NRF_PWM_LOAD_COMMON, //通用模式
|
||||
.step_mode = NRF_PWM_STEP_AUTO //序列中的周期自动推进
|
||||
};
|
||||
APP_ERROR_CHECK(nrfx_pwm_init(&m_pwm_dac, &config0, NULL));//初始化PWM
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* name : void PwmDACPlay(void)
|
||||
* description : 播放充能PWM
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void PwmDACPlay(void)
|
||||
{
|
||||
//定义PWM播放序列,播放序列包含了PWM序列的起始地址、大小和序列播放控制描述
|
||||
nrf_pwm_sequence_t const seq =
|
||||
{
|
||||
.values.p_common = dac_values,//指向PWM序列
|
||||
.length = NRF_PWM_VALUES_LENGTH(dac_values),//PWM序列中包含的周期个数
|
||||
.repeats = 0, //序列中周期重复次数为0
|
||||
.end_delay = 0 //序列后不插入延时
|
||||
};
|
||||
//启动PWM序列播放,flags设置为NRFX_PWM_FLAG_LOOP:序列播放完成后,自动触发任务重新播放
|
||||
(void)nrfx_pwm_simple_playback(&m_pwm_dac, &seq, 1, NRFX_PWM_FLAG_LOOP);
|
||||
}
|
||||
void SetPWMValues(uint16_t tempvalue)
|
||||
{
|
||||
*dac_values = CYCLE_CALUE - tempvalue;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* name : void PwmDACStop(void)
|
||||
* description : 停止播放充能PWM
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void PwmDACStop(void)
|
||||
{
|
||||
nrfx_pwm_stop(&m_pwm_dac,1);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* name : void pwm0_common_init(void)
|
||||
* description : 电流控制PWM初始化
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void pwm0_common_init(void)
|
||||
{
|
||||
//定义PWM初始化配置结构体并初始化参数
|
||||
nrfx_pwm_config_t const config0 =
|
||||
{
|
||||
.output_pins =
|
||||
{
|
||||
BASE_WAVE_06_PIN,
|
||||
BASE_WAVE_07_PIN,
|
||||
BASE_WAVE_08_PIN,
|
||||
NRFX_PWM_PIN_NOT_USED
|
||||
},
|
||||
.irq_priority = APP_IRQ_PRIORITY_LOWEST,//中断优先级
|
||||
.base_clock = NRF_PWM_CLK_1MHz, //PWM时钟频率设置为16MHz
|
||||
.count_mode = NRF_PWM_MODE_UP, //向上计数模式
|
||||
.top_value = 0, //使用波形装载模式时,该值被忽略
|
||||
.load_mode = NRF_PWM_LOAD_WAVE_FORM, //独立装载模式
|
||||
.step_mode = NRF_PWM_STEP_AUTO //序列中的周期自动推进
|
||||
};
|
||||
//初始化PWM
|
||||
APP_ERROR_CHECK(nrfx_pwm_init(&m_pwm0, &config0, NULL));
|
||||
|
||||
/////////////
|
||||
//pwm0_play();
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void pwm0_play(void)
|
||||
* description : 电流控制PWM开始播放
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void pwm0_play(void)
|
||||
{
|
||||
//定义PWM播放序列,播放序列包含了PWM序列的起始地址、大小和序列播放控制描述
|
||||
nrf_pwm_sequence_t const seq0 =
|
||||
{
|
||||
.values.p_wave_form = seq0_current_values,//指向PWM序列
|
||||
.length = NRF_PWM_VALUES_LENGTH(seq0_current_values),//PWM序列中包含的周期个数
|
||||
.repeats = 0, //序列中周期重复次数为0
|
||||
.end_delay = 0 //序列后不插入延时
|
||||
};
|
||||
//启动PWM序列播放,flags设置为NRFX_PWM_FLAG_LOOP:序列播放完成后,自动触发任务重新播放
|
||||
//如改为NRFX_PWM_FLAG_STOP,则播放结束后,PWM停止
|
||||
(void)nrfx_pwm_simple_playback(&m_pwm0, &seq0, 1,
|
||||
NRFX_PWM_FLAG_LOOP);
|
||||
}
|
||||
|
||||
void pwm0_stop(void)
|
||||
{
|
||||
nrfx_pwm_stop(&m_pwm0, 1);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void pwm2_common_init(void)
|
||||
* description : 电流控制PWM初始化
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void pwm2common_init(void)
|
||||
{
|
||||
//定义PWM初始化配置结构体并初始化参数
|
||||
nrfx_pwm_config_t const config0 =
|
||||
{
|
||||
.output_pins =
|
||||
{
|
||||
BOOST_VOLTAGE_CONTROL_PIN,
|
||||
NRFX_PWM_PIN_NOT_USED,
|
||||
NRFX_PWM_PIN_NOT_USED,
|
||||
NRFX_PWM_PIN_NOT_USED
|
||||
},
|
||||
.irq_priority = APP_IRQ_PRIORITY_LOWEST,//中断优先级
|
||||
.base_clock = NRF_PWM_CLK_16MHz, //PWM时钟频率设置为16MHz
|
||||
.count_mode = NRF_PWM_MODE_UP, //向上计数模式
|
||||
.top_value = 0, //使用波形装载模式时,该值被忽略
|
||||
.load_mode = NRF_PWM_LOAD_WAVE_FORM, //独立装载模式
|
||||
.step_mode = NRF_PWM_STEP_AUTO //序列中的周期自动推进
|
||||
};
|
||||
//初始化PWM
|
||||
APP_ERROR_CHECK(nrfx_pwm_init(&m_pwm2, &config0, NULL));
|
||||
|
||||
/////////////
|
||||
//pwm2_play();
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void pwm2_play(void)
|
||||
* description : 电流控制PWM开始播放
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void pwm2_play(void)
|
||||
{
|
||||
//定义PWM播放序列,播放序列包含了PWM序列的起始地址、大小和序列播放控制描述
|
||||
nrf_pwm_sequence_t const seq2 =
|
||||
{
|
||||
.values.p_wave_form = seq2_current_values,//指向PWM序列
|
||||
.length = NRF_PWM_VALUES_LENGTH(seq2_current_values),//PWM序列中包含的周期个数
|
||||
.repeats = 0, //序列中周期重复次数为0
|
||||
.end_delay = 0 //序列后不插入延时
|
||||
};
|
||||
//启动PWM序列播放,flags设置为NRFX_PWM_FLAG_LOOP:序列播放完成后,自动触发任务重新播放
|
||||
//如改为NRFX_PWM_FLAG_STOP,则播放结束后,PWM停止
|
||||
(void)nrfx_pwm_simple_playback(&m_pwm2, &seq2, 1,
|
||||
NRFX_PWM_FLAG_LOOP);
|
||||
}
|
||||
|
||||
void pwm2_stop(void)
|
||||
{
|
||||
nrfx_pwm_stop(&m_pwm2, 1);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void GpioteInit(void)
|
||||
* description : 刺激的任务GPIOTE初始化
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void GpioteInit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* name : void PPIPwmInit(void)
|
||||
* description : 刺激PWM的PPI初始化
|
||||
* Input : void
|
||||
* Output : void
|
||||
* Return :
|
||||
********************************************************************/
|
||||
void PPIPwmInit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*************************** END OF FILE ***************************/
|
||||
|
||||
|
||||
|
||||
32
app/Src/user_config.c
Normal file
32
app/Src/user_config.c
Normal file
@@ -0,0 +1,32 @@
|
||||
/********************************************************************
|
||||
Copyright (c) 2025 Xiangyu Medical Co.,Ltd. All rights reserved.
|
||||
FileName : spi.c
|
||||
Author : xiaozhengsheng
|
||||
Version : V1.0
|
||||
Date :
|
||||
Note :
|
||||
History :
|
||||
********************************************************************/
|
||||
/* Includes ------------------------------------------------------*/
|
||||
#include "user_config.h"
|
||||
//Log需要引用的头文件
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
|
||||
version_t softVersion={
|
||||
.major = 1,
|
||||
.minor = 0,
|
||||
.patch = 0, // 修订号 (.0)
|
||||
.build = 0, // 构建号 (.0)
|
||||
.testVersion = {"alpha1-1"} //内部测试版本,正式发布需要填0,alpha内部测试
|
||||
};
|
||||
|
||||
char softWareVersion[SOFT_VERSION_MAX_LENGTH] = {0}; //软件版本号
|
||||
|
||||
void read_config_user_config(void)
|
||||
{
|
||||
snprintf(softWareVersion, SOFT_VERSION_MAX_LENGTH, "V%d.%d.%d.%d-%s", softVersion.major, softVersion.minor, softVersion.patch, softVersion.build, softVersion.testVersion);
|
||||
NRF_LOG_INFO("Software Version: %s", softWareVersion);
|
||||
NRF_LOG_INFO("product model: HL-PDJ-1");
|
||||
}
|
||||
Reference in New Issue
Block a user