title: 年前STM32作品总结
tags: 总结
date: 2019-1-30 10:53:00
最近做了一些项目包括公司和个人的
自己平时很少玩32项目,所以还是比较吃力的,但是也勉强完成了这个项目。
src="//player.bilibili.com/player.html?aid=41993140&cid=73725287&page=1" scrolling="no" border="0" allowfullscreen="true">实际的运行效果
从这个作品里 我真的学到了很多知识,有关STM32作品的知识,其实这也算我人生中第一个真正意义上的STM32作品,因为我之前确实没玩过STM32,也没有做过相关的项目,到了公司以后才开始真正的接触STM32,而且一上来就是STM32F4的芯片,当时我一脸懵逼,又怕赶不上大家的步伐,所以我就抓紧时间学习了一下32的知识,看了一些教程,有的是视频教程买更多的还是看代码,拷贝粘贴,再修改。最终历时半个月,终于算是完成了这个作品。
- 项目来源:网上的朋友让我给他做毕业设计,收费的哦。
- 传感器选型:基本都是一些常用的传感器除了GSM模块(后来发现这玩意儿贼简单5行代码搞定)
- 遇到的瓶颈,作为一个初学者,还是遇到了很多问题的,比如我代码中注释的,例如IO方向的设置,模拟量的读取、I2C通讯协议的问题(不求甚解吧)
下面是main函数的代码:
#include "led.h"
#include "delay.h"
#include "dht11.h" //温湿度传感器库
#include "sys.h"
#include "usart.h"
#include "usart2.h"
#include "OLED.h"
#include "ds1302.h" //时钟模块库
#include "adc.h" //ADC采样库
#include "motor.h" //步进电机库
#include "key.h"
#include "beep.h"
#include "stmflash.h"
#include "iic.h" //I2C库 用于驱动光照传感器
#include "BH1750.h" //光照传感器库
#define FLASH_SAVE_ADDR 0X0800fe00 //设置FLASH 保存地址(必须为偶数,且其值要大于本代码所占用FLASH的大小+0X08000000)
//本代码由 阿正整理(部分原创)
//B站视频链接: https://www.bilibili.com/video/av41993140/
//本人小白 很少玩 STM32 这是第一个STM32作品,代码过于粗糙 也没时间整理,大神勿喷。
//转载请注明出处,欢迎加群一起学习;476840321
u16 test_flash = 100;
u16 data[1]={0}; //要写入的数据
uint8_t *bth_msg;
u16 adcx,dlx,ch2o=0;
u8 temperature=0; //温度
u8 humidity=0; //湿度
u16 set_T = 10; //定时 小时
u16 set_M = 10; //定时 分钟
int oled_clrflag = 0,guang_set=80; //光照初始值
int chuang_flag = 0;
unsigned char cc[10] = "AT\r\n";
unsigned char hh[20] = "AT+CMGF=1\r\n";
unsigned char gsm[20] = "AT+CSCS=\"GSM\"\r\n";
unsigned char hm[40] = "AT+CMGS=\"17739782188\"\r\n"; //改成你的手机号
unsigned char xx[10] = "hello"; //报警信息
void DisInit();
void read_flash();
void HW_int();
void seting_oled ();
void send_GSM();
void open_chuang();
void close_chuang();
void float_char(float f,unsigned char *s);
unsigned char Dec2Asc(unsigned char input, char* output );
typedef union //测试结构体
{
float f;
unsigned char u[10];
}Float4Byte;
int main(void)
{
unsigned char txd_data;
unsigned int txd_databuffer;
#if USESPI
SPI1_Config();
DMA_SPI_Config();
#endif
u8 t,time[15],len;
Float4Byte m1;
float test = 8.12;
float temp;
float datalx;
u16 times=0;
u8 DisFlag=0; //显示切换标志
int x ;
int KEY2_flag = 0;
SystemInit(); //配置系统时钟为
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组2
uart_init(9600); //主串口初始化为9600
usart2_init(9600); //串口2初始化9600 用于GSM通讯
LED_Init(); //初始化与LED连接的硬件接口
OLED_IOInit(); //OLEDIO初始化
OLED_Init(); //OLED初始化
Adc_Init(); //ADC初始化 A1 作为采集口
DHT11_Init(); //DHT11初始化 PC13
DS1302_Init(); //DS1302初始化
Motor_Init(); //步进电机初始化
HW_int(); //人体红外初始化
iic_init(); //i2c初始化
KEY_Init(); //按键初始化
Beep_Init(); //蜂鸣器初始化
bh_data_send(BHPowOn);
bh_data_send(BHReset);
bh_data_send(BHModeH2);
delay_ms(10);
//DS1302_Write_Time(); //初始化DS1302时间 时间不准确时,可以用它更新时间
DisInit(); //显示屏开机画面显示
delay_ms(1000); //延时单次不能延时大于1000
delay_ms(1000); //延时
OLED_Fill(0x00); //清屏
read_flash(); //读取flash数据
printf("\r\nflash存储的数据为:%d\r\n",test_flash);
while(1)
{
t=KEY_Scan(0); //得到键值
if(t!=0){
Beep=1;
delay_ms(100);
Beep=0;
}
//按键操作说明:在未进入设置页面情况下,上下按钮分别为开关窗,在进入设置页面后,上下按钮为设置阈值
if (t==KEY0_PRES){ //+
if(DisFlag == 1){
guang_set++;
}else if (DisFlag == 2){
set_M++;
if (set_M>59)set_M =59;
} else{
open_chuang();
}
}
if (t==KEY1_PRES){ //-
if(DisFlag ==1) {
guang_set--;
}else if (DisFlag == 2){
set_M--;
if (set_M<1)set_M =1;
} else{
close_chuang();
}
}
if (t==KEY2_PRES){ //设置翻页按钮
KEY2_flag++;
if (KEY2_flag>2) KEY2_flag = 0;
switch (KEY2_flag){
case 0:{
DisFlag=0;
}
break;
case 1:{
DisFlag=1;
oled_clrflag=1;
}
break;
case 2:{
DisFlag=2;
oled_clrflag=1;
}
break;
}
}
DS1302_Get_Time(time); //获取时钟模块时间
DHT11_Read_Data(&temperature,&humidity); //读取温湿度值
adcx=Get_Adc_Average(ADC_Channel_1,10); //读取ADC采样
temp=(float)adcx*(3.3/4096); //转换为3.3V数据量
ch2o=temp*1000;//先放大便于处理
datalx = bh_data_read()/1.2; //获取光照强度
dlx = datalx*1;
if(dlx>99) dlx=99;
if (dlx>guang_set) //自动开窗
{
if (chuang_flag == 0){
open_chuang();
}
}
if(time[11]*10+time[12] > set_M) //到达定时时间执行动作
{
if (chuang_flag == 0){
open_chuang();
}
}
x = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4); //读取红外状态
if (x && (chuang_flag)){ //检测人体
printf("dangerous");
Beep=1;
send_GSM(); //发送报警短信信息。
}else Beep=0;
// printf("%d%d%d%d年%d%d月%d%d日 ", time[0],time[1],time[2],time[3],time[4],time[5],time[6],time[7]);
// printf("%d%d时%d%d分%d%d秒 星期%d\n", time[9],time[10],time[11],time[12],time[13],time[14],time[8]);
if (DisFlag == 0){
//----------------------------------------//
LCD_P16x16Ch(32,0,27); //"环"
LCD_P16x16Ch(32+16,0,28); //"境"
LCD_P16x16Ch(32+32,0,29); //"检"
LCD_P16x16Ch(32+48,0,30); //"测"
LCD_P16x16Ch(32+64,0,31); //"仪"
//----------------------------------------//
LCD_P16x16Ch(0,2,25); //"烟雾"
LCD_P16x16Ch(16,2,26);
LCD_8x16Ch(32,2,ch2o/100%10);
LCD_8x16Ch(40,2,ch2o%100/10%10);
LCD_8x16Ch(48,2,ch2o%10%10);
//----------------------------------------//
LCD_P16x16Ch(64,2,32); //"光照"
LCD_P16x16Ch(80,2,33);
OLED_P8x16Str(96,2,":");
LCD_8x16Ch(104,2,dlx/10%10);
LCD_8x16Ch(112,2,dlx%10);
//----------------------------------------//
//------------温度------------//
LCD_P16x16Ch(0,4,0); //"温"
LCD_P16x16Ch(16,4,1); //"度"
OLED_P8x16Str(32,4,":");
LCD_8x16Ch(40,4,temperature/10%10);
LCD_8x16Ch(48,4,temperature%10);
//------------湿度------------//
LCD_P16x16Ch(66,4,2); //"湿"
LCD_P16x16Ch(66+16,4,3); //"度"
OLED_P8x16Str(66+32,4,":");
LCD_8x16Ch(66+40,4,humidity/10%10);
LCD_8x16Ch(66+48,4,humidity%10);
//------------时间------------//
LCD_P16x16Ch(0,6,23); //"时"
LCD_P16x16Ch(16,6,24); //"间"
OLED_P8x16Str(32,6,":");
LCD_8x16Ch(48,6,time[9]);
LCD_8x16Ch(56,6,time[10]);
OLED_P8x16Str(64,6,":");
LCD_8x16Ch(72,6,time[11]);
LCD_8x16Ch(80,6,time[12]);
}else if (DisFlag ==1){
if(oled_clrflag){
OLED_Fill(0x00);
oled_clrflag=0;
}
LCD_P16x16Ch(16,0,32); //"设置页面"
LCD_P16x16Ch(32,0,33);
LCD_P16x16Ch(48,0,34);
LCD_P16x16Ch(64,0,35);
LCD_P16x16Ch(80,0,36);
LCD_P16x16Ch(96,0,37);
LCD_P16x16Ch(0,2,32); //"光照"
LCD_P16x16Ch(16,2,33);
OLED_P8x16Str(32,2,":");
LCD_8x16Ch(40,2,guang_set/10%10);
LCD_8x16Ch(48,2,guang_set%10);
}else if (DisFlag ==2){
if(oled_clrflag){
OLED_Fill(0x00);
oled_clrflag=0;
}
LCD_P16x16Ch(16,0,23); //"设置页面"
LCD_P16x16Ch(32,0,24);
LCD_P16x16Ch(48,0,34);
LCD_P16x16Ch(64,0,35);
LCD_P16x16Ch(80,0,36);
LCD_P16x16Ch(96,0,37);
LCD_P16x16Ch(0,2,23); //"时间"
LCD_P16x16Ch(16,2,24);
OLED_P8x16Str(32,2,":");
LCD_8x16Ch(40,2,set_M/10%10);
LCD_8x16Ch(48,2,set_M%10);
}
delay_ms(100);
test_flash = 200;
data[0] = test_flash;
STMFLASH_Write(FLASH_SAVE_ADDR,data,1); //测试缓存数据
}
}
void open_chuang() //开窗
{
Motorcw_angle(180,10);
chuang_flag = 1;
}
void close_chuang() //关窗
{
Motorse_angle(180,10);
chuang_flag = 0;
}
/*
从flash读出保存的参数
*/
void read_flash()
{
u16 data[1]={0};
STMFLASH_Read(FLASH_SAVE_ADDR,data,1);
if(data[0]==0xffff) return; //如果为空,直接返回。
//取数据
test_flash=data[0];
//yyFlag =data[1];
}
void HW_int() //人体红外初始化
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能PE端时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // HWBZ-->PE1 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOA,&GPIO_InitStructure); //根据参数设定初始化GPIOE1
}
void DisInit()
{
OLED_Fill(0x00); //初始清屏
OLED_P8x16Str(0,0,"Hello my STM32");
OLED_P8x16Str(10,2,"2019 Come on!");
OLED_P8x16Str(10,6,"wenzheng.club");
}
void send_GSM() //发送报警短信
{
usart2_SendStringByLen(cc,sizeof(cc));
delay_ms(1000);
usart2_SendStringByLen(hh,sizeof(hh));
delay_ms(1000);
usart2_SendStringByLen(gsm,sizeof(gsm));
delay_ms(1000);
usart2_SendStringByLen(hm,sizeof(hm));
delay_ms(1000);
usart2_SendStringByLen(xx,sizeof(xx));
delay_ms(1000);
USART2SendByte(0x1A);
delay_ms(1000);
}
//学习笔记:
/*
注意:SIM800L供电为5V供电。
OLED显示的所有数据都是有位图组成的,且都存在于codetab.h中。
//OLED_P8x16Str(0,2,"ok"); 第一个参数为横坐标,第二个参数为纵坐标。
LCD_P16x16Ch(0,0,5); //中文字符取模存储在 codetab.h中
LCD_8x16Ch(48+16,2,temperature/10%10);
# 正点原子的代码单次延时不能超过1000 delay_ms(1000);
欲显示浮点型数据,需要把数据拼接(乘以1000)为整型,再取余即可
如: temp实际数值为1.700
u16 ch2o=0;
adcx=Get_Adc_Average(ADC_Channel_1,10);
temp=(float)adcx*(3.3/4096);
temp= temp*1000;
ch2o=temp;
LCD_8x16Ch(48,0,ch2o/1000);
OLED_P8x16Str(48+8,0,"."); //m
LCD_8x16Ch(48+16,0,ch2o%1000/100%10);
LCD_8x16Ch(48+24,0,ch2o%1000%100/10%10);
LCD_8x16Ch(48+32,0,ch2o%10);
下面是IO方向设置的代码**重要**
#define IIC_SDA_OUT() {GPIOC->CRH&=0X0FFFFFFF;GPIOC->CRH|=0x30000000;}//输入模式上拉下拉输入模式
#define IIC_SDA_IN() {GPIOC->CRH&=0X0FFFFFFF;GPIOC->CRH|=0x80000000;}//通用推挽输出50MZ
*/
具体的代码文件我已经上传到了群文件:阿正工作站
476840321