这次先看一下老朋友STM32,有关Zigbee的内容(Z-stack协议栈和基于Zigbee的环境温湿度+烟雾传感器的环境监测系统),等有时间再更。基于STM32的模拟液位检测告警系统,记得好像是某一届蓝桥杯省赛题~~
基于STM32告警系统介绍
“模拟液位检测告警系统”通过采集模拟电压信号计算液位高度,并根据用户设定的液位阈值执行报警动作,在液位等级发生变化时,通过串行通讯接口将液位信息发送到PC机。系统框图如下图所示:
任务要求
下面是我的代码,我都标了注释。
/****************功能*************************
* 文 件 名: 省赛题
* 作 者: 小舟%
* 描 述: 基于STM32的模拟液位检测告警系统
*********************************************/
/**********************************************
1.//USE_STDPERIPH_DRIVER,STM32F10X_MD
2.//解决了LCD与LED之间的冲突
3.//锁存器,与LED之间的关系更加清晰。 即 |开D2| reset |关D2|
4.//把LED的GPIO放入数组[]当中(方便流水,也方便操作)
5.//IIC初始化后要延时 5ms
//IIC读写操作要先 延时 后 读/写
6. sprintf([],"%.0")//取整数
sprintf([],"%.2")//取小数点后两位
*********************************************/
#include "stm32f10x.h"//从这往下都去掉
#include <stdio.h>//从这往下都去掉
#include "lcd.h"
#include "i2c.h"
#define k1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
#define k2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)
#define k3 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)
#define k4 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)
/*****************串口*******************************/
#define USARTz USART2
#define USARTz_GPIO GPIOA
#define USARTz_CLK RCC_APB1Periph_USART2
#define USARTz_GPIO_CLK RCC_APB2Periph_GPIOA
#define USARTz_RxPin GPIO_Pin_3
#define USARTz_TxPin GPIO_Pin_2
#define USARTz_IRQn USART2_IRQn
#define USARTz_IRQHandler USART2_IRQHandler
//****************************************************************************//
//0--全部
uint16_t led[]={GPIO_Pin_All,GPIO_Pin_8,GPIO_Pin_9,GPIO_Pin_10,GPIO_Pin_11,\
GPIO_Pin_12,GPIO_Pin_13,GPIO_Pin_14,GPIO_Pin_15};
//****************************************************************************//
float adc_value;
u8 adc_volt[20];///必须20///
u8 adc_heigh[20];
u8 adc_flag=0;
//-----
u8 dengji_num=0;//液面等级
u8 dengji_flag_now0=0;//当前液面等级 夹层
u8 dengji_flag_now1=0;
u8 deangji_change_flag=0;u8 dengji_increase=0;u8 dengji_down=0;u8 deangji_change_flag_chuankou[20];
u8 dengji[20];
//-----
u8 Threshold_mid[20];
u8 Threshold_heigh[20];
u8 Threshold_low[20];
//****************************************************************************//
u16 miao=0;
u16 led2time=0;
u32 TimingDelay = 0;
void Delay_Ms(u32 nTime);
//****************************************************************************//
u8 low=0;
u8 heigh=0;
u8 mid=0;
//****************************************************************************//
u8 keyB1flag=0; // 0---界面1
// 1---界面2
u8 LCD2_choise=0;//界面2的标红选择(1,2,3)
//****************************************************************************//
u8 yewei=0; //C
u8 fazhi=0; //S
float chuankou_heigh=0;
u8 chuankou_s[20];//串口打印sprintf
u8 chuankou_c[20];
//****************************************************************************//
u8 LED1_shanshuo_flag=0;
u8 LED2_shanshuo_flag=0;u8 LED2_shanshuo_time_flag=0;u8 chuankou_to_led2=0;//串口给的闪烁的信号
u8 led2_five=0;
u8 LED3_shanshuo_flag=0;u8 chuankou_chaxun_to_led3_flag=0;u8 i=0;
//****************************************************************************//
void Delay_Ms(u32 nTime);
void lcdinit(void);
void ledinit(void);
void keyinit(void);
void keyscan(void);
void adc_init(void);
void adc_read(void);
void usart_init(void);
void USART2_IRQHandler(void);
void usart_string(u8 *str);
u8 IICread(u8 addd);
void IICwrite(u8 addd,u8 data);
void dengji_panduan(void);
void LCDone(void);//第一个LCD界面
void LCDtwo(void);//第二个LCD界面
void LED1_shanshuo(void);
void LED3_shanshuo(void);//闪烁5次
void LED2_shanshuo(void);//闪烁5次
int main(void)
{
SysTick_Config(SystemCoreClock/1000);
lcdinit();
ledinit();
keyinit();
adc_init();
usart_init();
/*----------------------------------------------------------------------------*/
i2c_init();Delay_Ms(5);
if(IICread(0x10)!=99)
{
Delay_Ms(5);IICwrite(0x01,30);
Delay_Ms(5);IICwrite(0x02,50);
Delay_Ms(5);IICwrite(0x03,70);
Delay_Ms(5);IICwrite(0x10,99);
}
Delay_Ms(5);low=IICread(0x01);
Delay_Ms(5);mid=IICread(0x02);
Delay_Ms(5);heigh=IICread(0x03);
/*-------------------------------------------------------------------------------*/
while(1)
{
keyscan();
/*1秒采集ADC----第yi个时间线间隔1s*/
if(adc_flag==1)
{
adc_flag=0;
if(keyB1flag==0)
{LCDone();}
LED1_shanshuo();//LED1交替
}
/*LED2闪烁 ----第二个时间线间隔0.2s*/
if(LED2_shanshuo_time_flag==1)
{
LED2_shanshuo_time_flag=0;
//#LED3
if(chuankou_chaxun_to_led3_flag>0)
{
chuankou_chaxun_to_led3_flag=chuankou_chaxun_to_led3_flag-1;
LED3_shanshuo();
}
//#LED2
if(chuankou_to_led2>0)
{
chuankou_to_led2=chuankou_to_led2-1;
LED2_shanshuo();
}
}
/*等级变化串口输出*/
if(deangji_change_flag==1)
{
deangji_change_flag=0;
if(dengji_increase==1)
{dengji_increase=0;sprintf((char*)deangji_change_flag_chuankou,"%s%.2f%s%d%s","A:H",chuankou_heigh,"+L",dengji_num,"+U\r\n");}
if(dengji_down==1)
{dengji_down=0;sprintf((char*)deangji_change_flag_chuankou,"%s%.2f%s%d%s","A:H",chuankou_heigh,"+L",dengji_num,"+D\r\n");}
chuankou_to_led2=10;//串口给的闪烁的信号
usart_string(deangji_change_flag_chuankou);
}
/*串口测试*/
if(fazhi==1)//S
{
fazhi=0;
chuankou_chaxun_to_led3_flag=10;
sprintf((char*)chuankou_c,"%s%d%s%d%s%d%s","S:TL",low,"+TM",mid,"+TH",heigh,"\r\n");
usart_string(chuankou_c);//OK
}
/*串口测试*/
if(yewei==1)//C
{
yewei=0;
chuankou_chaxun_to_led3_flag=10;
//C:H55+L2\r\n
sprintf((char*)chuankou_s,"%s%.2f%s%d%s","C:H",chuankou_heigh,"+L",dengji_num,"\r\n");
usart_string(chuankou_s);//OK
}
}
}
void LED1_shanshuo()
{
GPIO_SetBits(GPIOD,GPIO_Pin_2);//gao
if(LED1_shanshuo_flag==0)
{
GPIO_ResetBits(GPIOC,led[1]);//低电平--点亮
LED1_shanshuo_flag=1;
}
else if(LED1_shanshuo_flag==1)
{
GPIO_SetBits(GPIOC,led[1]);//低电平--点亮
LED1_shanshuo_flag=0;
}
GPIO_ResetBits(GPIOD,GPIO_Pin_2);//di
}
void LED2_shanshuo()
{
GPIO_SetBits(GPIOD,GPIO_Pin_2);//gao
if(LED2_shanshuo_flag==0)
{
GPIO_ResetBits(GPIOC,led[2]);//低电平--点亮
LED2_shanshuo_flag=1;
}
else if(LED2_shanshuo_flag==1)
{
GPIO_SetBits(GPIOC,led[2]);//低电平--点亮
LED2_shanshuo_flag=0;
}
GPIO_ResetBits(GPIOD,GPIO_Pin_2);//di
}
void LED3_shanshuo()
{
GPIO_SetBits(GPIOD,GPIO_Pin_2);//gao
if(LED3_shanshuo_flag==0)
{
GPIO_ResetBits(GPIOC,led[3]);//低电平--点亮
LED3_shanshuo_flag=1;
}
else if(LED3_shanshuo_flag==1)
{
GPIO_SetBits(GPIOC,led[3]);//低电平--点亮
LED3_shanshuo_flag=0;
}
GPIO_ResetBits(GPIOD,GPIO_Pin_2);//di
}
u8 IICread(u8 addd)
{
u8 value;
I2CStart();
I2CSendByte(0xa0);
I2CSendAck();
I2CSendByte(addd);
I2CSendAck();
I2CStart();
I2CSendByte(0xa1);
I2CSendAck();
value=I2CReceiveByte();
I2CSendAck();
I2CStop();
return value;
}
void IICwrite(u8 addd,u8 data)
{
I2CStart();
I2CSendByte(0xa0);
I2CSendAck();
I2CSendByte(addd);
I2CSendAck();
I2CSendByte(data);
I2CSendAck();
I2CStop();
}
void Delay_Ms(u32 nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
void lcdinit()
{
STM3210B_LCD_Init();
LCD_Clear(Blue);
LCD_SetTextColor(Black);
LCD_SetBackColor(Green);
LCD_DisplayStringLine(Line0,(unsigned char *)" ");
LCD_DisplayStringLine(Line1,(unsigned char *)" Liquid Level/ ");
LCD_DisplayStringLine(Line2,(unsigned char *)" ");
LCD_DisplayStringLine(Line3,(unsigned char *)" Height: ");
LCD_DisplayStringLine(Line4,(unsigned char *)" ");
LCD_DisplayStringLine(Line5,(unsigned char *)" ADC: ");
LCD_DisplayStringLine(Line6,(unsigned char *)" ");
LCD_DisplayStringLine(Line7,(unsigned char *)" Level: ");
LCD_DisplayStringLine(Line8,(unsigned char *)" ");
LCD_DisplayStringLine(Line9,(unsigned char *)" ");
}
void LCDone()
{
LCD_SetTextColor(Black);
LCD_SetBackColor(Green);
adc_read();//ADC
LCD_DisplayStringLine(Line0,(unsigned char *)" ");
LCD_DisplayStringLine(Line1,(unsigned char *)" Liquid Level/ ");
LCD_DisplayStringLine(Line2,(unsigned char *)" ");
//LCD_DisplayStringLine(Line3,(unsigned char *)" Height: ");//取消后有间隔1s闪烁的效果
LCD_DisplayStringLine(Line4,(unsigned char *)" ");
//LCD_DisplayStringLine(Line5,(unsigned char *)" ADC: ");
LCD_DisplayStringLine(Line6,(unsigned char *)" ");
//LCD_DisplayStringLine(Line7,(unsigned char *)" Level: ");
LCD_DisplayStringLine(Line8,(unsigned char *)" ");
LCD_DisplayStringLine(Line9,(unsigned char *)" ");
}
void LCDtwo()
{
LCD_SetTextColor(Black);
LCD_SetBackColor(Green);
LCD_DisplayStringLine(Line0,(unsigned char *)" ");
LCD_DisplayStringLine(Line1,(unsigned char *)" Parameter Setup/ ");
LCD_DisplayStringLine(Line2,(unsigned char *)" ");
sprintf ((char*)Threshold_low,"%s%dcm%s"," Threshold 1: ",low," ");
LCD_DisplayStringLine(Line3,Threshold_low);
LCD_DisplayStringLine(Line4,(unsigned char *)" ");
sprintf ((char*)Threshold_mid,"%s%dcm%s"," Threshold 2: ",mid," ");
LCD_DisplayStringLine(Line5,Threshold_mid);
LCD_DisplayStringLine(Line6,(unsigned char *)" ");
sprintf ((char*)Threshold_heigh,"%s%dcm%s"," Threshold 3: ",heigh," ");
LCD_DisplayStringLine(Line7,Threshold_heigh);
LCD_DisplayStringLine(Line8,(unsigned char *)" ");
LCD_DisplayStringLine(Line9,(unsigned char *)" ");
if(LCD2_choise==1)
{
LCD_SetTextColor(Blue);
LCD_SetBackColor(Red);
sprintf ((char*)Threshold_low,"%s%dcm%s"," Threshold 1: ",low," ");//不带上只带下面的LCD函数 屏幕会出 BUG
LCD_DisplayStringLine(Line3,Threshold_low);
}
else if(LCD2_choise==2)
{
LCD_SetTextColor(Blue);
LCD_SetBackColor(Red);
sprintf ((char*)Threshold_mid,"%s%dcm%s"," Threshold 2: ",mid," ");
LCD_DisplayStringLine(Line5,Threshold_mid);
}
else if(LCD2_choise==3)
{
LCD_SetTextColor(Blue);
LCD_SetBackColor(Red);
sprintf ((char*)Threshold_heigh,"%s%dcm%s"," Threshold 3: ",heigh," ");
LCD_DisplayStringLine(Line7,Threshold_heigh);
}
}
void ledinit()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//记
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//记
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin =led[0];//GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10| GPIO_Pin_11| GPIO_Pin_12| GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//高电平打开锁存器
GPIO_SetBits(GPIOD,GPIO_Pin_2);//gao
GPIO_SetBits(GPIOC,led[0]);//低电平--点亮
GPIO_ResetBits(GPIOD,GPIO_Pin_2);//di
}
void keyinit()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//记
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//记
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//记
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//记
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void keyscan()
{
if(k1==0)
{
Delay_Ms(10);//10ms
if(k1==0)
{
/**/
if(keyB1flag==0)
{
keyB1flag=1;
LCDtwo();
}
else if(keyB1flag==1)
{
keyB1flag=0;
LCDone();
}
}
while(!k1);
}
if(k2==0)
{
Delay_Ms(10);//10ms
if(k2==0)
{
if(keyB1flag==1)//界面2
{
LCD2_choise=LCD2_choise+1;
if(LCD2_choise==4)
{LCD2_choise=1;}
LCDtwo();
}
}
while(!k2);
}
if(k3==0)
{
Delay_Ms(10);//10ms
if(k3==0)
{
if(keyB1flag==1)//界面2
{
if(LCD2_choise==1)
{
low=low+5;
if(low>95) {low=95;}
}
else if(LCD2_choise==2)
{
mid=mid+5;
if(mid>95) {mid=95;}
}
else if(LCD2_choise==3)
{
heigh =heigh+5;
if(heigh>95) {heigh=95;}
}
/**/
LCDtwo();
Delay_Ms(5);IICwrite(0x01,low);
Delay_Ms(5);IICwrite(0x02,mid);
Delay_Ms(5);IICwrite(0x03,heigh);
}
}
while(!k3);
}
if(k4==0)
{
Delay_Ms(10);//10ms
if(k4==0)
{
if(keyB1flag==1)//界面2
{
if(LCD2_choise==1)
{
low=low-5;
if(low<5) {low=5;}
}
else if(LCD2_choise==2)
{
mid=mid-5;
if(mid<5) {mid=5;}
}
else if(LCD2_choise==3)
{
heigh =heigh-5;
if(heigh<5) {heigh=5;}
}
LCDtwo();
Delay_Ms(5);IICwrite(0x01,low);
Delay_Ms(5);IICwrite(0x02,mid);
Delay_Ms(5);IICwrite(0x03,heigh);
}
}
while(!k4);
}
}
void adc_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);/时钟//
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOB, &GPIO_InitStructure);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel14 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_13Cycles5);
/* Enable AWD interrupt */
ADC_ITConfig(ADC1, ADC_IT_AWD, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable ADC1 reset calibration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
}
void dengji_panduan()
{
if(adc_value<low)
{
dengji_num=0;
sprintf((char*)dengji,"%s%d%s"," Level: ",dengji_num," ");
}
else if((adc_value>low)&&(adc_value<=mid))
{
dengji_num=1;
sprintf((char*)dengji,"%s%d%s"," Level: ",dengji_num," ");
}
else if((adc_value>mid)&&(adc_value<=heigh))
{
dengji_num=2;
sprintf((char*)dengji,"%s%d%s"," Level: ",dengji_num," ");
}
else if(adc_value>heigh)
{
dengji_num=3;
sprintf((char*)dengji,"%s%d%s"," Level: ",dengji_num," ");
}
}
void adc_read()
{
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
adc_value=ADC_GetConversionValue(ADC1)*3.30/0xfff;
sprintf((char*)adc_volt ,"%s%.2fV%s"," ADC: ",adc_value," ");
LCD_DisplayStringLine(Line5,adc_volt);
adc_value=adc_value*30.303;
chuankou_heigh=adc_value;
sprintf((char*)adc_heigh ,"%s%.2fcm%s"," Height: ",adc_value," ");
LCD_DisplayStringLine(Line3,adc_heigh);
dengji_flag_now0=dengji_num;
dengji_panduan();//等级判断函数
dengji_flag_now1=dengji_num;
if(dengji_flag_now0!=dengji_flag_now1)
{
deangji_change_flag=1;//
if(dengji_flag_now1>dengji_flag_now0)
{dengji_increase=1;}
else if(dengji_flag_now1<dengji_flag_now0)
{dengji_down=1;}
}
LCD_DisplayStringLine(Line7,dengji);
}
void usart_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB1PeriphClockCmd(USARTz_CLK, ENABLE);
RCC_APB2PeriphClockCmd(USARTz_GPIO_CLK , ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = USARTz_RxPin;
GPIO_Init(USARTz_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = USARTz_TxPin;
GPIO_Init(USARTz_GPIO, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure USARTz */
USART_Init(USARTz, &USART_InitStructure);
/* Enable USARTz Receive and Transmit interrupts */
USART_ITConfig(USARTz, USART_IT_RXNE, ENABLE);
/* Enable the USARTz */
USART_Cmd(USARTz, ENABLE);
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* Enable the USARTz Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USARTz_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void USART2_IRQHandler()
{
u8 temp;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != 0)
{
//USART_ClearITPendingBit(USART2, USART_IT_RXNE);
temp= USART_ReceiveData(USART2);
if(temp=='C')
{
yewei=1;
}
else if(temp=='S')
{
fazhi=1;
}
}
}
void usart_string(u8 *str)
{
while(*str)
{
while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==0); //判断是否可以发送
USART_SendData(USART2,*str);
while(USART_GetFlagStatus(USART2, USART_FLAG_TC)==0); //判断是否发送完成
//成只发送最后一个字符(覆盖)
str++;
}
}
ok,上面是我在main.c文件里的全部代码,蓝桥的板子下载没用FLYMCU或是ARM仿真器,有专门的CooCox下载,下面看一下实验现象~
1.液位检测
2.液位阈值设定
3.液位阈值设定
4、串口查询与输出功能
5.状态指示
emmm…有时间的我会更新和补充其他届的省赛赛题,希望能对大家有所帮助~~