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