一.电刺激部分
E_S连接MCU的IO口 控制HEF4011BT工作与否,当三级管导通时,C41处输出震荡波,震荡频率由C19和R3决定。
C41隔直通交,滤除部分直流
Q2和Q3形成一个直推图腾柱,增大推动能力,使得后端MOS管可正常处于深度打开状态
XL2596Vout处经R22形成一个负反馈
E端接IO口输出PWM,占空比越大时,等效输入电压越大,再通过三极管,此时电路形成小电流控大流。增大占空比即可增大输出电压,同时后端输出电压变化,经变压器、电极后输出到人体
二.变压器电路简述
电感线圈本身会有阻抗,这点不容忽视,原边阻值即限流电阻阻值+自身感抗,副边同理。
当电极短路时,相当副边负载0欧姆,初级线圈自身电感感抗也会变为0,此时所有的能量经续流二极管经限流电阻消耗掉,并不会对人体造成伤害。
三.超声接入信号预处理
四.电机模块
采用L9110S电机驱动芯片,M_IN1and M_IN2接IO口输出PWM,同样可以通过占空比控制转速,2路信号可控正反转。(5V小电机)
外部可接两个机械限位开关,使得导药到极限位置时暂停。
五.超声驱动模块
原理与电机驱动近似
六.迪文屏人机交互
组态界面迪文官方有专门的教程,不做过多描述。
此处连接要注意串接电阻大小
七.代码部分
MCU使用的是STM32F103C8T6
GPIO、定时器、串口和硬件IIC的基础配置此处不做讲解,考虑到迪文屏的数据量可能比较大,串口信息传递部分我是使用DMA,
void MX_DMA_Init(void)
{
//开启DMA时钟
__HAL_RCC_DMA1_CLK_ENABLE();
//开启中断,使能DMA
HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart,uint16_t Size)
{
if (huart==&huart3)
{
//HAL_UART_Transmit_DMA(&huart3,ReceiveData,Size);
HAL_UARTEx_ReceiveToIdle_DMA(&huart3,ReceiveData,sizeof(ReceiveData));
__HAL_DMA_DISABLE_IT(&hdma_usart3_rx,DMA_IT_HT);
Instruct();
}
}
void Instruct (void)//这个函数当时为了判断上位机发送数据,写的是一言难尽
{
if(ReceiveData[0] ==0x5A)
{
if(ReceiveData[1] ==0xA5)
{
if(ReceiveData[2] ==0x06)
{
if(ReceiveData[3] ==0x83)
{
if(ReceiveData[4] ==0x20)
{
if(ReceiveData[5] ==0x00)
{
if(ReceiveData[6] ==0x01)
{
if(ReceiveData[7] ==0x00)
{
if(ReceiveData[8] ==0x01)
{
GG =1;//电机回退
BB=0;
HAL_UART_Transmit_DMA(&huart3,MotorArray,8);
}
else if(ReceiveData[8] ==0x00)
{
GG =0;//电机回退停止
}}}}}}}}}
输入捕获测频率并反馈到迪文屏显示
void capture(void)//输入捕获测频率
{
switch(captyre_bit)
{
case 0:
captyre_bit++;
TIM_RESET_CAPTUREPOLARITY(&htim4,TIM_CHANNEL_1);//清空状态
TIM_SET_CAPTUREPOLARITY(&htim4,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);//捕获高电平
HAL_TIM_IC_Start_IT(&htim4,TIM_CHANNEL_1);
break;
case 3:
high_time = captyre_buf[1] - captyre_buf[0];//高电平时间
printf("%d",captyre_buf[1]);
printf("%d",captyre_buf[0]);
printf("%d",high_time);
HAL_Delay(1000);
captyre_bit=0;
break;
}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//输入捕获中断函数
{
if(htim->Instance == TIM4)//判断是否定时器4产生
{
switch(captyre_bit)
{
case 1:
captyre_buf[0] = HAL_TIM_ReadCapturedValue(&htim4,TIM_CHANNEL_1);//读取捕获值
captyre_bit++;
break;
case 2:
captyre_buf[1] = HAL_TIM_ReadCapturedValue(&htim4,TIM_CHANNEL_1);//读取捕获值
HAL_TIM_IC_Stop_IT(&htim4,TIM_CHANNEL_1);
captyre_bit++;
break;
}
}
}
PWM档位调节
void ultrasound(void)//超声功率档位调节 频率1~20Hz 1.30% 2.60% 3.100%
{
switch(c)
{
case 1:__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,30);
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,0);
break;
case 2:__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,60);
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,0);
break;
case 3:__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,80);
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,0);
break;
}
}
main函数
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t ZZTArray[]={ZTH,ZTL,ZL,ZW,ZAH,ZAL,ZTime,ZMinute,ZSecond};
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_11,GPIO_PIN_SET);//电刺激初始停止
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_RESET);//芯片状态灯
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_TIM1_Init();
MX_USART3_UART_Init();
MX_TIM2_Init();
MX_CRC_Init();
MX_I2C1_Init();
MX_TIM3_Init();
MX_TIM4_Init();
MX_USART2_UART_Init();
MX_ADC1_Init();
/* USER CODE BEGIN 2 */
HAL_UARTEx_ReceiveToIdle_DMA(&huart3,ReceiveData,sizeof(ReceiveData));
__HAL_DMA_DISABLE_IT(&hdma_usart3_rx,DMA_IT_HT);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
capture();
if(AA==1 && DD==1)//电极
{
ElectrodeStart();
Electrode();
}
else
{
ElectrodeStop();
}
if( DD==1)//电机
{
if(BB==1)//电机回退后重新开始若卡住,delay500ms
{
MotorStart();
Motor();
}
else if(GG==1)
{
MotorStart();
Motor_rollback();
}
else if( GG==0 )
{
MotorStop();
}
}
else if(DD==0)
{
MotorStop();
}
if(CC==1 && DD==1)//超声 默认连续模式
{
ultrasoundStart();
ultrasound();
}
else
{
ultrasoundStop();
}
printf("%d",a);
printf("%d",b);
printf("%d",c);
printf("%d",AA);
printf("%d",BB);
printf("%d",CC);
printf("%d",DD);
//串口发送计时数据
HAL_Delay(1000);
if(DD==1)
{
WordTime();
ZZTArray[6]=ZTime;
ZZTArray[7]=ZMinute;
ZZTArray[8]=ZSecond;
HAL_UART_Transmit_IT(&huart3,ZZTArray,9);
}
else
{
ZTime=0;
ZMinute=0;
ZSecond=0;
ZZTArray[6]=0;
ZZTArray[7]=0;
ZZTArray[8]=0;
HAL_UART_Transmit_IT(&huart3,ZZTArray,9);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
这是本人23年毕业后入职做的第一个商业性项目,代码写的和那个啥一样,硬件部分也并没有考虑成本,介于公司的产权,本人并不能将实际产品发出供大家参考。以它来作为我在CSDN的初始篇,后续也会发一些其他的项目以及一些踩过的坑和小技巧,欢迎大家提出宝贵意见,评论区留言我也会答复。在此再次感谢带我入门并启蒙嵌入式的杨博士。