自动感应垃圾桶c语言,如何使用STM32开发板作一个自动感应垃圾桶

1、所用到的软件和硬件

软件:

使用的KEIL 和STM32CUBE MX

STM32CUBE MX简直小白福音,若是对于STM32配置不是很清楚的话,又想尝试STM32芯片的开发的话,能够尝试使用这一个软件,这个能够想图形同样的点点就配置成功了。

硬件:

STM32F103ZET6的开发板、一个单刀单掷的继电器、一个双刀双掷的继电器、一个红外线感应模块、一个光电开关

b2b1135b790e34a4532814501ce7695c.png

上图少了红外线模块和光电开关web

2、硬件的用途

单刀单掷的继电器:用来作一个电机电源的开关,电机一旦上电就会一直转,容易形成堵转,因此须要一个电源的开关

双刀双掷的继电器:用用来作一个电源的反转,达到电机反转的目的

红外线感应器:做为一个传感器,感应物体接近

开发板:做为处理器

电机:一上电就会一直转,因此须要断电,防止堵转过久,烧坏了svg

3、代码的编写和整理

引脚说明:

PA4 引脚输出 若是是高电平,单刀单掷的继电器闭合,电机电源导通

PA3 引脚输出 若是是高电平,双刀双掷的继电器闭合,电机电源反转

PA5 引脚中断 若是是高电平,进入中断

PA7 引脚中断 若是是高电平,进入中断函数

主函数程序

初始化完毕,在while(1)里,一直检测是否有信号输入,有信号,进入中断标志位置1。优化

int main(void)

{

HAL_Init();

SystemClock_Config();

MX_GPIO_Init();

while (1)

{

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); //程序运行,电源打开A

My_Delay_us(50);

if(INR == 1) //判断有没有红外线感应,若是有,进入Deal_Infared函数,进行开关门动做

{

Deal_Infared();

}

if(SW_STA == 1) //判断有没有合上,若是合上,进去Deal_Switch,关闭电源

{

Deal_Switch();

}

}

中断处理程序函数

在中断处理函数里,尽可能不要放太多语句处理,尽可能简洁一点,我这边的话是设置一个标志位,若是有信号进入就把标志位置1 若是直接在处理函数处理开门关门的操做 有可能会错过一些传感器的信号ui

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) //一接收到红外线感应,进入中断

{

if(GPIO_Pin == GPIO_PIN_5) //判断是否是5口 红外线

{

My_Delay_us(10); //延迟10us

if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_5) == SET)

{

INR = 1;

}

}

if(GPIO_Pin == GPIO_PIN_7) //判断是否是7口 光电开关

{

My_Delay_us(10); //延迟10us

if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7) == RESET)

{

SW_STA = 1;

}

}

}

红外线感应到的处理函数

void Deal_Infared() //处理红外线的函数

{

//完成开门动做

while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7) == RESET ) // 这个是防止门没开起来,由于光电开关检测到位就会断电

{

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);

My_Delay_us(50);

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); //电源开启,一直开门

}

//INR = 0; //标志位置0,等待下次进入中断

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); //电源关闭

My_Delay_us(50);

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET); //若是收到红外线感应模块的反馈,就电机反转,打开垃圾桶

My_Delay_us(50);

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); //电源开启

HAL_Delay(3000);

while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_5) == SET)//判断红外线有没有再次感应到,若是有,电源继续开着,直到没有感应到

{

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); //电源开启

}

//完成关门动做

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); //电源关闭

//My_Delay_us(50);

HAL_Delay(500);

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET); //完成关门动做

INR = 0; //标志位置0,等待下次进入中断

}

关门断电函数

void Deal_Switch(void) //定义开关函数

{

while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7) == RESET & INR != 1) //这个是检测若是关门到位,就关闭电源,防止电机堵转烧坏

{

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); //电源开启,关门到位

My_Delay_us(100);

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); //电源关闭

}

SW_STA = 0;

}

4、后面的优化思路

1.这个电机正转反转是用继电器控制,接线十分繁琐,可使用电机驱动器,使用PWM输出控制,能达到正反转的效果,也能达到控制电机的速度

2.这边的延时是HAL_DELAY,延迟就堵塞了,正常的代码通常不会使用这个,由于这样太消耗资源,如何达到延迟却不堵塞,再这个代码延迟的时候,能够去执行其余线程呢,能够加入freeRTOS系统,通常用在项目中的也是使用这个系统。

这两个我都有组装和写好代码,须要能够再发,很简易的电路,适合刚入门的人试试水。spa