前言:
从一月十九日写下的草稿箱开始学习51单片机,到现在学习完32。
不知觉已经经历了四个月的时间,简单的调整方向后决定通过一个STM32的小案例进行巩固32的学习。
这次的案例没有教程,通过自己现有的一些设备来完成这样的一个小实验。代码可能不够高效,方法可能不是很好,却是对自己的一个检验。
知识获取来源于哔哩哔哩江科大的32教程,以及其他UP的视频。
设计思路:
首先从整体来看是一个有三种控制的LED灯,但是不局限于LED灯,可以通过连接其他外设或者继电器来控制更多的设备。整体上来说是一个三模的操控系统。
classDiagram
Butten <|-- AD
Butten <|-- Serial
Butten <|-- Key
Butten : uint8_t KeyNum
Butten : uint8_t Ligh_Detect_Flag
Butten: Butten_Init()
Butten: Butten_Control()
Butten : Butten_Show()
class AD{
AD_Init()
quack()
}
class Serial{
uint8_t RxData_Flag
-canEat()
}
class Key{
Key_Init()
Key_GetNum()
}
主要可以集成到Butten类里,在本身的Butten类中引用了AD、Serial、Key。
-
Butten中主要有三个函数
- Init()| 进行初始化,包括各个函数的初始化,以及时钟、GPIO、中断、OLED展示的初始化。
- Control() | 主要对状态机的判断,执行相对应的操作。
- Show() | 进行OLED功能展示,判断标志位以及GPIO高低电平来显示对应信息。
-
在Butten中通过Key提供的Key_GetNum()函数来获取按下的键码值,来进行开关灯以及光敏模块的开关操作。
-
通过引用AD,获取ADC转换后的结果并展示出来,同时配置ADC中模拟看门狗以及对应中断,通过中断的方式来实现天黑自动关灯,天亮自动开灯的功能。
-
通过引用Serial,配置串口接收中断。在收到蓝牙发送的特定信息来执行相应操作,开关灯以及开关光敏模块的功能。因为用的是HC-08,所以暂时只能用商家提供的蓝牙调试软件,因此暂时没有设计回传状态的功能。
演示
由于掘金平台只能上传西瓜的视频,但是又不想去发布西瓜的视频,因此将视频转换为GIF的格式进行展示,当然观感也会下降,但是可以看出来效果。
按键演示:
光敏模块演示:
蓝牙演示:
具体代码实现:
- Button
#ifndef __BUTTON_H
#define __BUTTON_H
extern uint8_t KeyNum;
extern uint8_t Light_Detect_Flag;
void Butten_Init(void);
void Butten_Control(void);
#endif
#include "stm32f10x.h" // Device header
#include "LED.h"
#include "Key.h"
#include "OLED.h"
#include "AD.h"
#include "Timer.h"
#include "Serial.h"
#include "../System/Delay.h"
float Data;
uint8_t KeyNum;
uint16_t Data_Temp;
uint8_t Light_Detect_Flag = 1 ;
void Butten_Show(void);
void Light_Detect_Turn(void);
void Butten_Init(void)
{
LED_Init();
Key_Init();
AD_Init();
Serial_Init();
OLED_ShowString(1,1,"LED:OFF");
OLED_ShowString(2,1,"Detect: ON");
}
void Butten_Control(void)
{
KeyNum = Key_GetNum();
if (KeyNum == 1 )
{
LED0_Turn();
}
else if (KeyNum == 2)
{
Light_Detect_Turn();
}
Butten_Show();
}
void Butten_Show(void)
{
if (GPIO_ReadOutputDataBit(GPIOA , GPIO_Pin_0) == 1)
{
OLED_ShowString(1,1,"LED:OFF");
}
else
{
OLED_ShowString(1,1,"LED: ON");
}
if (Light_Detect_Flag == 1)
{
OLED_ShowString(2,1,"Detect:OFF");
OLED_ShowString(3 , 1 , " " );
}else if (Light_Detect_Flag == 0)
{
OLED_ShowString(2,1,"Detect: ON");
Data_Temp = ADC_GetConversionValue(ADC1);
Data = (float)Data_Temp / 4095 * 100 ;
OLED_ShowNum(3 , 1 , Data, 2);
OLED_ShowChar(3, 3 ,'%');
OLED_ShowNum(3 , 5 , (float)(AD_GetLightH() + 100 ) / 4095 * 100 , 2);
OLED_ShowChar(3, 7 ,'%');
OLED_ShowNum(3 , 10 , (float)(AD_GetLightL() + 100 ) / 4095 * 100, 2);
OLED_ShowChar(3, 12 ,'%');
Delay_ms(100);
}
if (RxData_Flag == 1)
{
OLED_ShowString(4 ,1 , "LED0-ON");
Delay_ms(100);
OLED_ShowString(4, 1, " ");
RxData_Flag = 0;
}
else if (RxData_Flag == 2)
{
OLED_ShowString(4 ,1 , "LED0-OFF");
Delay_ms(100);
OLED_ShowString(4, 1, " ");
RxData_Flag = 0;
}
else if (RxData_Flag == 3)
{
Light_Detect_Turn();
RxData_Flag = 0;
}
}
void Light_Detect_Turn(void)
{
if (Light_Detect_Flag == 1)
{
Light_Detect_Flag = 0 ;
}else if (Light_Detect_Flag == 0)
{
LED0_OFF();
Light_Detect_Flag = 1 ;
}
}
void ADC1_2_IRQHandler(void)
{
if(ADC_GetITStatus(ADC1 , ADC_IT_AWD) == SET)
{
if (Light_Detect_Flag == 0)
{
if (ADC_GetConversionValue(ADC1) < 2000)
{
LED0_OFF();
}
else if (ADC_GetConversionValue(ADC1) > 3000)
{
LED0_ON();
}
}
ADC_ClearITPendingBit(ADC1 , ADC_IT_AWD);
}
}
- Key
#ifndef __KEY_H
#define __KEY_H
void Key_Init(void);
uint8_t Key_GetNum(void);
#endif
#include "stm32f10x.h"
#include "Delay.h"
void Key_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
GPIO_Init(GPIOB , &GPIO_InitStructure);
}
uint8_t Key_GetNum()
{
uint8_t KeyNum = 0;
if(GPIO_ReadInputDataBit(GPIOB , GPIO_Pin_1) == 0 )
{
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOB , GPIO_Pin_1) == 0)
Delay_ms(20);
KeyNum = 1 ;
}
if(GPIO_ReadInputDataBit(GPIOB , GPIO_Pin_11) == 0 )
{
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOB , GPIO_Pin_11) == 0)
Delay_ms(20);
KeyNum = 2 ;
}
return KeyNum;
}
- AD
#ifndef __AD_H
#define __AD_H
void AD_Init(void);
uint16_t AD_GetLightH(void);
uint16_t AD_GetLightL(void);
#endif
#ifndef __KEY_H
#define __KEY_H
void Key_Init(void);
uint8_t Key_GetNum(void);
#endif
#include "stm32f10x.h"
#define Light_Pin GPIO_Pin_5
#define Light_Channel ADC_Channel_5
#define Light_High 3200
#define Light_Low 2000
void AD_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //预分频
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = Light_Pin;
GPIO_Init(GPIOA , &GPIO_InitStructure);
ADC_RegularChannelConfig(ADC1 , Light_Channel , 1 , ADC_SampleTime_55Cycles5);
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent ; //ADC独立模式
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right ;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
//ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //不连续转换
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 连续转换
ADC_InitStructure.ADC_NbrOfChannel = 1; //连续转换通道数
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //扫描模式
ADC_Init(ADC1 , &ADC_InitStructure);
ADC_Cmd(ADC1 , ENABLE);
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1));
ADC_AnalogWatchdogSingleChannelConfig(ADC1, Light_Channel);
ADC_AnalogWatchdogThresholdsConfig(ADC1, Light_High, Light_Low);
ADC_AnalogWatchdogCmd(ADC1, ADC_AnalogWatchdog_SingleRegEnable);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =2 ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =2 ;
NVIC_Init(&NVIC_InitStructure);
ADC_ITConfig(ADC1 , ADC_IT_AWD , ENABLE);
ADC_SoftwareStartConvCmd(ADC1,ENABLE); //连续转换时放这里
}
uint16_t AD_GetLightH(void)
{
return Light_High;
}
uint16_t AD_GetLightL(void)
{
return Light_Low;
}
- Serial
#ifndef __SERIAL_H
#define __SERIAL_H
#include <stdio.h>
extern uint8_t RxData_Flag;
void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array , uint16_t Length);
void Serial_SendString(char *String);
uint32_t Serial_Pow(uint32_t x, uint32_t y);
void Serial_SendNumber(uint32_t Number , uint8_t Length);
void Serial_Printf(char *format , ...);
uint8_t Serial_GetRxFlag(void);
uint8_t Serial_GetRxData(void);
#endif
#include "stm32f10x.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdio.h>
#include "LED.h"
uint8_t Serial_RxData;
uint8_t Serial_RxFlag;
uint8_t RxData_Flag;
void Serial_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 ,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOA , &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_9);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA , &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_10);
USART_InitTypeDef USART_InitSruture;
USART_InitSruture.USART_BaudRate = 9600;
USART_InitSruture.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitSruture.USART_Mode =USART_Mode_Tx | USART_Mode_Rx ;
USART_InitSruture.USART_Parity =USART_Parity_No ; //odd 奇校验 even 偶校验
USART_InitSruture.USART_StopBits =USART_StopBits_1 ;
USART_InitSruture.USART_WordLength =USART_WordLength_8b ;
USART_Init(USART1 , &USART_InitSruture);
USART_ITConfig(USART1 ,USART_IT_RXNE , ENABLE );
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef Nvic_InitStructure;
Nvic_InitStructure.NVIC_IRQChannelCmd = ENABLE;
Nvic_InitStructure.NVIC_IRQChannel = USART1_IRQn;
Nvic_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
Nvic_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&Nvic_InitStructure);
USART_Cmd(USART1 , ENABLE);
}
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1 , Byte);
while (USART_GetFlagStatus(USART1 , USART_FLAG_TXE) == RESET);
}
void Serial_SendArray(uint8_t *Array , uint16_t Length)
{
uint16_t i ;
for ( i = 0; i < Length; i++)
{
Serial_SendByte(Array[i]);
}
}
void Serial_SendString(char *String)
{
uint8_t i;
for(i = 0 ; String[i] != 0 ; i++)
{
Serial_SendByte(String[i]);
}
}
uint32_t Serial_Pow(uint32_t x, uint32_t y)
{
uint32_t Result =1 ;
while (y--)
{
Result *= x;
}
return Result;
}
void Serial_SendNumber(uint32_t Number , uint8_t Length)
{
uint8_t i ;
for ( i = 0; i < Length; i++)
{
Serial_SendByte(Number / Serial_Pow(10 , Length - i - 1 ) % 10 + '0');
}
}
int fputc(int ch , FILE *f)
{
Serial_SendByte(ch);
return ch;
}
void Serial_Printf(char *format , ...)
{
char String[100];
va_list arg;
va_start(arg , format);
vsprintf(String , format , arg);
va_end(arg);
Serial_SendString(String);
}
uint8_t Serial_GetRxFlag(void)
{
if (Serial_RxFlag == 1)
{
Serial_RxFlag = 0 ;
return 1;
}
return 0 ;
}
uint8_t Serial_GetRxData(void)
{
return Serial_RxData ;
}
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1 , USART_IT_RXNE) == SET)
{
if (USART_ReceiveData(USART1) == 1)
{
LED0_ON();
RxData_Flag = 1;
}
else if (USART_ReceiveData(USART1) == 2)
{
LED0_OFF();
RxData_Flag = 2;
}
else if (USART_ReceiveData(USART1) == 3)
{
RxData_Flag = 3;
}
USART_ClearITPendingBit(USART1 , USART_IT_RXNE);
}
}