基于stm32 的简单的智慧农业系统, 有上位机,有下位机

1. 实现的功能

1. 下位机(stm32) (keil 5 )

        1. 按键key1 中断控制 LED 3 的亮灭

        2. 按键key2  中断控制  温湿度的获取, (数据通过串口发送给 上位机)

        3. 智能检测温湿度是否超标, (超标 开启警报, 开启风扇)

        4.OLED  显示 温湿度,(每次获取温湿度,更新数据)

        5. 设置窗口看门狗, 保证程序不会出现异常, (中断喂狗)

2. 上位机

        1. 按钮1   通过串口通信控制 LED 3 的亮灭

        2. 按钮2   通过串口通信控制  蜂鸣器的开启与关闭 

        3. 按键3   通过 串口通信 获取温湿度的数据  

        4.  旋钮,通过 串口通信  调节 呼吸灯LED1 的亮度 (PWM 技术控制)


 2. 制作过程中遇到的问题

1. 串口通信的时候  下位机接收的 问题  ( 接收函数,判定数据正确的条件有一个 语句后面需要加 \r\n   )     之前的串口调试工具是自动加的,  所以我这里出现了问题。 

2. Dht11 温湿度传感器  的时序图的 解读有一点问题, 我之前以为获取数据是只要发送一次起始信号就可以无限获取数据,  但是程序的实验结果告诉我们, 发送一次起始数据, 判断一次 传感器的高低电平数据, 才可以接收一次数据,  而且我们的传感器启动的时候,需要停止  1秒 启动。

3. PWM 控制呼吸灯的时候,发现有程序控制的 LED 3  (比如说是中断),  不可以使用 PWM 的函数控制。  PWM  控制的LED   在主程序里面不可以被控制, 只能通过 PWM 的控制函数控制。

4.  在智能检测温湿度是否超标  的时候需要加一个特判 , 才能防止 超标代码对其他功能的妨碍.

5. OLED  的取模是一个  技术活。!!

6.每一个 程序的功能需要 单独测试 , 封装成函数更好!!


3.代码:  (板子不同,硬件的引脚可能不同,程序功能不同)

(板子   stm32 f407VET6 )

下位机: (自己写的 片上外设的控制 文件) (系统的文件自己找, )  (资源已经上传, 0积分 ))

基于stm32 的简单的智慧农业系统, 有上位机,有下位机_第1张图片

 main.cpp 

#include "BEEP.h"//蜂鸣器
#include "KEY.h"//按键
#include "LED.h"//LED
#include "motor.h"// 电风扇
#include "delay.h"//延时函数
#include "myiic.h"//IIC  
#include "oled.h"//oled 屏幕显示 
#include "MyDht11.h"// 温湿度传感器
#include "myusart.h"//串口通信
#include "stdio.h"
#include "PWM.h"//PWM  控制是灯光的亮度
#include "wwdg.h"
#include "misc.h"
#include "stm32f4xx_exti.h"
#include "MYEXIT.h"


void oled_dht11_display(void);//把温度显示在oled上面
void oled_display_x_y(int a,int b,char  ff);//oled 屏幕字符显示
void led_twinkle(void);// 第二个灯的闪烁   
void wanning_open(void);// 打开警报
void wanning_close(void);//关闭警报

//全局变量
char a111,a222;  //a111 湿度,  a222 温度


int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	ledinit();//LED 灯初始化
	key_init();//按键初始化
	beepinit();//蜂鸣器初始化0p
	motor_init();// 电机初始化
	delay_init(168);//延时初始化
	IIC_Init();//IIC  初始化
	InitOLed();//oled 初始化
	myusart_init(115200);// 串口通信初始化
	DHT11_init();//温湿度传感器初始化
	TIM14_PWM_Init();	//呼吸灯初始化
	wwdginit();//窗口看门狗 初始化
	MYEXIT_init();//中断初始化
	
	int len;
	int panduan=0;
	while(1) 
	{
			if(a222>26)
			{
			  	wanning_open();
				  panduan=1;
			}
			else
			{
				if(panduan==1)
				{
						wanning_close();
					  panduan=0;
				}
				
			}
		if(USART_RX_STA&0x8000)
		{					   
			   len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
					
		    	if(len <=3)
			   {
							int a1=(int)(USART_RX_BUF[0] -48);
							if(a1==1)//开灯
							{
									select_led(3);
							}
							if(a1==2)//关灯
							{
									close_num_led(3);
							}
							if(a1==3)//开蜂鸣器
							{
								
									openBeep();//打开蜂鸣器警报
							}
							if(a1==4)//关闭蜂鸣器
							{
									closeBeep();//关闭蜂鸣器  
							}
							if(a1==5)
							{
									oled_dht11_display();
									led_twinkle();
							}
							if(a1==0)
							{
									if(len<=3)
									{
											int a2=(int)(USART_RX_BUF[1] -48)*10;
											int a3=(int)(USART_RX_BUF[2] -48);
											int a4=a2+a3;
											ppp(a4);
									
									}
									
									
							}
								
								
							
					}
			
			    USART_RX_STA=0;
		}
	}
	
	
		
	
}


void wanning_open()
{
		openBeep();//打开蜂鸣器警报
		motor_ON();//打开 风扇电机	

}

void wanning_close()
{
	closeBeep();//关闭蜂鸣器  
	motor_OFF();//关闭 风扇电机	
	
}


void oled_display_x_y(int a,int b,char  ff)
{
		  char nn = ff/10;
			char mm = ff%10;
			if(nn==0)
			{
					OLed_ShowASCII(a,b,"0");  //显示英文。
			}
			else if(nn==1)
			{
					OLed_ShowASCII(a,b,"1");  //显示英文。
			}
			else if(nn==2)
			{
					OLed_ShowASCII(a,b,"2");  //显示英文。
			}
			else if(nn==3)
			{
					OLed_ShowASCII(a,b,"3");  //显示英文。
			}
			else if(nn==4)
			{
					OLed_ShowASCII(a,b,"4");  //显示英文。
			}
			else if(nn==5)
			{
					OLed_ShowASCII(a,b,"5");  //显示英文。
			}
			else if(nn==6)
			{
					OLed_ShowASCII(a,b,"6");  //显示英文。
			}
			else if(nn==7)
			{
					OLed_ShowASCII(a,b,"7");  //显示英文。
			}
			else if(nn==8)
			{
					OLed_ShowASCII(a,b,"8");  //显示英文。
			}
			else if(nn==9)
			{
					OLed_ShowASCII(a,b,"9");  //显示英文。
			}
			
			
			if(mm==0)
			{
					OLed_ShowASCII(a+8,b,"0");  //显示英文。
			}
			else if(mm==1)
			{
					OLed_ShowASCII(a+8,b,"1");  //显示英文。
			}
			else if(mm==2)
			{
					OLed_ShowASCII(a+8,b,"2");  //显示英文。
			}
			else if(mm==3)
			{
					OLed_ShowASCII(a+8,b,"3");  //显示英文。
			}
			else if(mm==4)
			{
					OLed_ShowASCII(a+8,b,"4");  //显示英文。
			}
			else if(mm==5)
			{
					OLed_ShowASCII(a+8,b,"5");  //显示英文。
			}
			else if(mm==6)
			{
					OLed_ShowASCII(a+8,b,"6");  //显示英文。
			}
			else if(mm==7)
			{
					OLed_ShowASCII(a+8,b,"7");  //显示英文。
			}
			else if(mm==8)
			{
					OLed_ShowASCII(a+8,b,"8");  //显示英文。
			}
			else if(mm==9)
			{
					OLed_ShowASCII(a+8,b,"9");  //显示英文。
			}
			

}

void oled_dht11_display()//把温度显示在oled上面
{
		
	
		OLed_ShowChina(0,0,HZ4);
		OLed_ShowChina(16,0,HZ5);
		OLed_ShowChina(32,0,HZ6);
		OLed_ShowChina(48,0,HZ7);
		OLed_ShowChina(64,0,HZ8);
		OLed_ShowChina(80,0,HZ9);
		OLed_ShowChina(96,0,HZ10);
		OLed_ShowChina(112,0,HZ11);
	
	  if(DHT11_ReadData(&a111,&a222)==0)
		{
				delay_ms(1000);
				//printt("oled ",a111);		
				printt("oled ",a222);		
		}
		
			OLed_ShowChina(0,2,HZ1);
			OLed_ShowChina(16,2,HZ2);
			oled_display_x_y(48,2,a222);
			OLed_ShowChina(64,2,HZ2);
	
			//第2行显示湿度
		
			OLed_ShowChina(0,4,HZ3);
			OLed_ShowChina(16,4,HZ2);
			oled_display_x_y(48,4,a111);
			OLed_ShowASCII(64,4,"%");
		
		

}

void led_twinkle(void)//第二个灯的闪烁
{
	 int i;
	 int k=0;
	
			if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_9)==1) // 记录现在的状态
			{
					k=1;
			}
			else 
			{
				 k=2;
			}
			
			
			//闪烁
			for(i=0;i<5;i++)
			{
					select_led(2);
					delay_ms(100);
					close_num_led(2);
					delay_ms(100);
			}
			//还原原来的状态
			if(k==1)
			{
					close_num_led(2);
			}
			else if(k==2)
			{
				select_led(2);
					
			}
}


void EXTI9_5_IRQHandler(void)
{

	  if(EXTI_GetITStatus(EXTI_Line5) != RESET)//按下KEY2
   { 
			oled_dht11_display();
			led_twinkle();
			EXTI_ClearITPendingBit(EXTI_Line5);
   }
	 
   //else if(EXTI_GetITStatus(EXTI_Line6) != RESET)  //按下KEY3
   //{
        
		//		EXTI_ClearITPendingBit(EXTI_Line6);
   //}
	 
}



1. BEEP .h 

#ifndef __BEEP_H__
#define __BEEP_H__

 
void beepinit(void);//初始化
void openBeep(void);//打开蜂鸣器
void closeBeep(void);//关闭蜂鸣器
 
 


#endif


2.BEEP.c

#include "stm32f4xx.h"  //头文件
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "beep.h"
void beepinit(void)
{
	
	//1.时钟问题解决
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);//
	//2.引脚配置问题解决
	GPIO_InitTypeDef beepstruct;//设置变量
	beepstruct.GPIO_Mode= GPIO_Mode_OUT;//输出模式  //引脚输出信号
	beepstruct.GPIO_OType=GPIO_OType_PP;//外部无上拉电阻选择推挽输出,  外部有上拉电阻选择开漏输出
	beepstruct.GPIO_Pin=GPIO_Pin_10;//引脚的编号是哪个
	beepstruct.GPIO_PuPd=GPIO_PuPd_UP; //上拉电阻
	beepstruct.GPIO_Speed=GPIO_Low_Speed;//配置速度
	
	GPIO_Init(GPIOB,&beepstruct);
	//3.初始化
	GPIO_ResetBits(GPIOB,GPIO_Pin_10);//设置输出低电平 ,开始的时候让他不响
}
 
void openBeep(void)//打开蜂鸣器
{
	//GPIO_WriteBit(GPIOB,GPIO_Pin_10,Bit_SET);//打开蜂鸣器
	GPIO_SetBits(GPIOB,GPIO_Pin_10);//打开蜂鸣器
}
 
 
void closeBeep(void)//关闭蜂鸣器
{
	//GPIO_WriteBit(GPIOB,GPIO_Pin_10,Bit_RESET);//关闭蜂鸣器
	GPIO_ResetBits(GPIOB,GPIO_Pin_10);//设置输出低电平 ,开始的时候让他不响
}
 

  3.KEY.h 

#ifndef __KEY_H__
#define __KEY_H__
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
void key_init(void);//初始化key 
int key_youxi(void);//key  按键的游戏
 
 

#endif


4.KEY.c

#include "stm32f4xx.h"  //头文件
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "key.h"
 
void key_init(void)//初始化key 
{
	
		//初始key1  key2  key3
	//1.时钟问题解决
		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
		GPIO_InitTypeDef keystruct;//设置变量
		keystruct.GPIO_Mode=GPIO_Mode_IN; //输入模式  //引脚输入信号
		keystruct.GPIO_Pin=GPIO_Pin_4 |GPIO_Pin_5 |GPIO_Pin_6;// 三个按键一起初始化  
		//keystruct.GPIO_OType  输出类型不需要
		keystruct.GPIO_PuPd=GPIO_PuPd_UP;//需要上拉电阻
		keystruct.GPIO_Speed=GPIO_Low_Speed;//速度
		GPIO_Init(GPIOE,&keystruct);
	
		//初始化
		GPIO_SetBits(GPIOE,GPIO_Pin_4|GPIO_Pin_5 |GPIO_Pin_6);//给这些按键高电平  key1  key2  key3
	
	
	//初始化 key4
		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
		GPIO_InitTypeDef keystruct1;//设置变量
		keystruct1.GPIO_Mode=GPIO_Mode_IN; //输入模式  //引脚输入信号
		keystruct1.GPIO_Pin=GPIO_Pin_13;// 按键一起初始化  
		//keystruct.GPIO_OType  输出类型不需要
		keystruct1.GPIO_PuPd=GPIO_PuPd_UP;//需要上拉电阻
		keystruct1.GPIO_Speed=GPIO_Low_Speed;//速度
		GPIO_Init(GPIOC,&keystruct1);
		
		GPIO_SetBits(GPIOC,GPIO_Pin_13);//给这些按键高电平  key4
		
}


int key_youxi(void)//key  按键的游戏
{
			int i;
			if(!GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4))//这个函数是高电平返回 1  低电平 返回 0 
			{
					for(i=10000;i>0;i--);//消抖
					if(!GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4))
					{
						while(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0);
						return 1;
					}
					
			}
			
			if(!GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_5))//这个函数是高电平返回 1  低电平 返回 0 
			{
					for(i=10000;i>0;i--);//消抖
					if(!GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_5))
					{
						while(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_5)==0);
						return 2;
					}
			}
			
			if(!GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_6))//这个函数是高电平返回 1  低电平 返回 0 
			{
					for(i=10000;i>0;i--);//消抖
					if(!GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_6))
					{
						while(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_6)==0);
						return 3;
					}
					
			}
			
			if(!GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13))//这个函数是高电平返回 1  低电平 返回 0 
			{
					for(i=10000;i>0;i--);//消抖
					if(!GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13))
					{
						while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)==0);
						return 4;
					}
			}
			return 0;
}


5. LED.h

#ifndef __LED_H__
#define __LED_H__
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
 
void delay(void);// for  延时
void ledinit(void);//初始化
void select_led(int a);//假如a !=  1 2 3 ,就关闭所有的灯
void liushui_led(void);// 展示流水灯的程序
void close_led(void );//关闭所有的小灯
void close_num_led(int a);//关闭指定的小灯


#endif




6. LED.c

#include "stm32f4xx.h"  //头文件
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "led.h"
void delay()//延时函数
{
	int b=5000000;
	while(b--)//形成延时函数
	{
		
	}
}
 
void ledinit()
{
		//led 低电平驱动
	//3 个led 可控制,一个不可控制
	//二极管单向导通,阳极固定高电平,阴极输出高电平,led 灭
	//二极管单向导通,阳极固定高电平,阴极输出低电平,led 亮
	GPIO_InitTypeDef GIOSTRUCT;
	
	
	//1.配置时钟: 给个心跳。 选择需要的时钟频率
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
	
	//2.配置功能: 功能太多。 选择GPIO功能;
	GIOSTRUCT.GPIO_Mode=GPIO_Mode_OUT ; //输出模式  //引脚输出信号
	GIOSTRUCT.GPIO_Pin=GPIO_Pin_8 |GPIO_Pin_9 |GPIO_Pin_10;//led 灯的引脚 
	GIOSTRUCT.GPIO_PuPd=GPIO_PuPd_UP;  //上拉电阻
	GIOSTRUCT.GPIO_Speed=GPIO_Low_Speed;//配置速度
	//外部无上拉电阻选择推挽输出,  外部有上拉电阻选择开漏输出
	GIOSTRUCT.GPIO_OType=GPIO_OType_PP;
	GPIO_Init(GPIOE,&GIOSTRUCT);
	
	//GPIO_Init(GPIOE,&GIOSTRUCT);
	
	
	//3.操作引脚: 输出低电平 led 亮,  输出高电平 led灭
	
	//初始化
	GPIO_SetBits(GPIOE,GPIO_Pin_8 |GPIO_Pin_9 |GPIO_Pin_10 );//把灯都关了
	
	//GPIO_ResetBits  输出低电平
	//GPIO_SetBits    输出高电平
 
}
 
 
void select_led(int a)//假如a !=  1 2 3 ,就关闭所有的灯
{
	
	
	if(a==1)
	{
			GPIO_ResetBits(GPIOE,GPIO_Pin_8);//串口组, 引脚//打开第一个灯
	}
	if(a==2)
	{
			GPIO_ResetBits(GPIOE,GPIO_Pin_9);//串口组, 引脚//打开第二个灯
	}
	if(a==3)
	{
			GPIO_ResetBits(GPIOE,GPIO_Pin_10);//串口组, 引脚//打开第三个灯
	}
 
}

void close_num_led(int a)//关闭指定的小灯
{
	if(a==1)
	{
			GPIO_SetBits(GPIOE,GPIO_Pin_8 );//把灯都关了
	}
	if(a==2)
	{
			GPIO_SetBits(GPIOE,GPIO_Pin_9);//把灯都关了
	}
	if(a==3)
	{
			GPIO_SetBits(GPIOE,GPIO_Pin_10 );//把灯都关了
	}


}


void close_led(void )//关闭所有的小灯
{
	GPIO_SetBits(GPIOE,GPIO_Pin_8 |GPIO_Pin_9 |GPIO_Pin_10 );//把灯都关了
}
 
 
void liushui_led()//流水灯 , 功能: 从第一个灯 轮流闪烁 一直到最后一个灯,最后把所有的灯关闭。
{
		GPIO_SetBits(GPIOE,GPIO_Pin_8 |GPIO_Pin_9 |GPIO_Pin_10 );//把灯都关了
			GPIO_ResetBits(GPIOE,GPIO_Pin_8);//串口组, 引脚//打开第一个灯
			
		delay();
	  GPIO_SetBits(GPIOE,GPIO_Pin_8 |GPIO_Pin_9 |GPIO_Pin_10 );//把灯都关了
			GPIO_ResetBits(GPIOE,GPIO_Pin_9);//串口组, 引脚//打开第二个灯
	
	  delay();
	  GPIO_SetBits(GPIOE,GPIO_Pin_8 |GPIO_Pin_9 |GPIO_Pin_10 );//把灯都关了
			GPIO_ResetBits(GPIOE,GPIO_Pin_10);//串口组, 引脚//打开第三个灯
		delay();
	
	GPIO_SetBits(GPIOE,GPIO_Pin_8 |GPIO_Pin_9 |GPIO_Pin_10 );//把灯都关了
}


7. motor.h

#ifndef __MOTOR_H__
#define __MOTOR_H__

void motor_init(void);//风扇初始化
#define motor_ON()   GPIO_SetBits(GPIOB,GPIO_Pin_15);//给e组的8个引脚低电平
#define motor_OFF()   GPIO_ResetBits(GPIOB,GPIO_Pin_15);//给e组的8个引脚低电平


// 请按下按键2 让第三个灯亮和灭
#endif


8.motor.c

#include "motor.h"
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
void motor_init(void)
{
			 GPIO_InitTypeDef GPIO_InitStruct ;
    
    //第一步:AHB1总线上的E组引脚时钟使能;(心脏开始跳动)
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);

    //设置gpio结构体
   GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15  ;   //控制哪一个引脚  PE8
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; // 设置引脚为输出
   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;  //设置输出速度
   GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;   //推挽方式
   GPIO_InitStruct.GPIO_PuPd  = GPIO_PuPd_UP;  //设置高电平还是低电平
    //设置GPIO口寄存器数据
   GPIO_Init(GPIOB,&GPIO_InitStruct);
   GPIO_ResetBits(GPIOB,GPIO_Pin_15);//关闭电机

}


9. MyDht11.h

#ifndef __MYDHT11_H__
#define __MYDHT11_H__

#include "stm32f4xx.h"
void DHT11_init(void);     //初始化
void DHT11_InMode(void);  //模式变为 输入模式
void DHT11_OutMode(void);// 模式变为 输出模式
unsigned char  DHT11_Read_Bit(void);//获取一位的 u8 数据
unsigned char DHT11_ReadData(char * humi,char *temp);//获取 5 个u8 数据, 进行校验和
void dht11_play_data(void);//输出数据
#endif


10. MyDht11.c

#include "MyDht11.h"
#include "stm32f4xx.h"
#include "delay.h"
#include "myusart.h"


char buff[5] = "";
char humi = 0 ,temp = 0 ;

char flg = 100 ,flg1 = 100;

//读出来的数据是16进制也没事。把二进制发送上位机也没事。只要是一个字节就行。 

//引脚:PA3
void DHT11_init()
{
		//1,配置时钟
		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
		//2.配置引脚
		GPIO_InitTypeDef DHT11struct;
		//填写引脚
		DHT11struct.GPIO_Pin = GPIO_Pin_3;
		//填写速度
		DHT11struct.GPIO_Speed = GPIO_Speed_2MHz;
		DHT11struct.GPIO_PuPd = GPIO_PuPd_NOPULL ;
		//填写电阻
		DHT11struct.GPIO_Mode = GPIO_Mode_OUT;
		//即可以输出高电平也可以输出低电平
		DHT11struct.GPIO_OType = GPIO_OType_OD;
		GPIO_Init(GPIOA,&DHT11struct);
		//把引脚拉高。
		GPIO_SetBits(GPIOA,GPIO_Pin_3);
		
}
//输入模式函数
void DHT11_InMode()
{
		//配置引脚
		GPIO_InitTypeDef DHT11struct;
		//填写引脚
		DHT11struct.GPIO_Pin = GPIO_Pin_3;
		//填写速度
		DHT11struct.GPIO_Speed = GPIO_Speed_2MHz;
		//填写电阻
		DHT11struct.GPIO_Mode = GPIO_Mode_IN;
		DHT11struct.GPIO_PuPd = GPIO_PuPd_NOPULL ;
		//即可以输出高电平也可以输出低电平
		GPIO_Init(GPIOA,&DHT11struct);
}

//输入模式函数
void DHT11_OutMode()
{
		//配置引脚
		GPIO_InitTypeDef DHT11struct;
		//填写引脚
		DHT11struct.GPIO_Pin = GPIO_Pin_3;
		//填写速度
		DHT11struct.GPIO_Speed = GPIO_Speed_2MHz;
		//填写电阻
		//即可以输出高电平也可以输出低电平
		DHT11struct.GPIO_OType = GPIO_OType_OD;
		DHT11struct.GPIO_Mode = GPIO_Mode_OUT;
		DHT11struct.GPIO_PuPd = GPIO_PuPd_NOPULL ;
		GPIO_Init(GPIOA,&DHT11struct);
		GPIO_SetBits(GPIOA,GPIO_Pin_3);
	
}
unsigned char  DHT11_Read_Bit()
{
			unsigned char readbit = 0 ;
			unsigned int i = 0 ;
			for(i = 0 ; i < 8 ; i++)
			{
						//为了避免最高位被移出去。
						readbit = readbit << 1 ;
						//1在内部也要等待高电平结束。因为在循环过程中,有高电平的持续时间。
						//高电平是上一个周期的数据
						while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3));
				
						//2等待引脚变为高电平,如果是低电平就卡主,等低电平结束
						while(!GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3));
						//如果是高电平持续30us
						//这里是读位数据。
						//如果高电平持续时间较长,也就是30us之后还是高电平
						if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3))
						{
								//如果读到的是高电平并且 50us以后又读一次还是高电平。
								delay_us(30);
						}
						//又读一次还是高电平,那么久写数据1,否则就是低电平。
						if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3))
								readbit |= 1 ;
						else	
								readbit |= 0 ;
						
			}
			return readbit;
}


unsigned char DHT11_ReadData(char * humi,char *temp)
{
			unsigned char num = 0 ;
			unsigned int i = 0 ;
			//1.主机发送开始信号20ms,低电平20ms。至少拉低。
			GPIO_ResetBits(GPIOA,GPIO_Pin_3);
			delay_ms(20);
	
			//2.主机拉高30us
			GPIO_SetBits(GPIOA,GPIO_Pin_3);
			delay_us(30);
	
			DHT11_InMode();
			//如果发过来的是高电平,就等待高电平结束。
			//因为外拉电阻,如果读到的是高电平,就等待高电平结束。
			while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3));
			//3如果读到的是低电平,那么就等待低电平结束。
			while(!GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3))
			{				
						//响应信号
						flg = 0xee ;
			}
			//4等待高电平结束。高点平持续时间太久也不行。
			while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3))
			{		//如果低电平持续的时间太长,那么也要退出。
					delay_us(4);
					num++;
					if(num > 20)
							return 1;
			}
			//高电平一旦结束,那么就是信号来了。
			//开始读数据
				
//					buff[0] = DHT11_Read_Bit();
//					buff[1] = DHT11_Read_Bit();
//					buff[2] = DHT11_Read_Bit();
//					buff[3] = DHT11_Read_Bit();
//					buff[4] = DHT11_Read_Bit();
			
			
			for(i = 0 ; i < 5 ; i++)
			{
					//读五次数据,五个字节。
					buff[i] = DHT11_Read_Bit();
			}
			//函数结束以后要把引脚调整为输出模式
			DHT11_OutMode();	
			//5.校验数据
			if(buff[4] == buff[0] + buff[1] + buff[2] + buff[3] )
			{
						*humi = buff[0];
						*temp = buff[2] ;
						i = 0 ;
						return 0;
			} 
			else
						return 1 ;
}

void dht11_play_data(void)
{
	char a1,a2;
	if(DHT11_ReadData(&a1,&a2)==0)
		{
				delay_ms(1000);
				printt("湿度是:",a1);		
				printt("温度是:",a2);		
			
		}



}

11.MYEXIT.h 

#ifndef __MYEXIT_H__
#define __MYEXIT_H__

void MYEXIT_init(void);//初始化


#endif



12.MYEXIT.c

#include "MYEXIT.h"
#include "stm32f4xx.h"  //头文件
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "KEY.h"
#include "LED.h"
#include "delay.h"
#include "MyDht11.h"


void MYEXIT_init(void)//初始化
{
    EXTI_InitTypeDef EXTI_InitStructure;
		NVIC_InitTypeDef NVIC_InitStruct;
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);//中断使能
		//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//分组
	

		SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource4);//绑定端口
		SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource5);//绑定端口


		
	  EXTI_InitStructure.EXTI_Line = EXTI_Line5 | EXTI_Line4 ;//那根中断线
	  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//设置中断和事件
		EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
		EXTI_InitStructure.EXTI_LineCmd = ENABLE; //中断使能
		EXTI_Init(&EXTI_InitStructure);
	
		NVIC_InitStruct.NVIC_IRQChannel = EXTI4_IRQn;
		NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority =1;//设置抢占优先级
		NVIC_InitStruct.NVIC_IRQChannelSubPriority =1; //设置响应优先级
		NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能
		NVIC_Init(&NVIC_InitStruct);
		
		NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn;
		NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority =1;//设置抢占优先级
		NVIC_InitStruct.NVIC_IRQChannelSubPriority =0; //设置响应优先级
		NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能
		NVIC_Init(&NVIC_InitStruct);
	
}



void EXTI4_IRQHandler(void)
{
	static int LED=1;
	delay_ms(20);
	if(key_youxi()==1)
	{
		    if(LED%2==1)
				{
					select_led(3);
					LED=0;
				}
				else if(LED%2==0)
				{
					close_num_led(3);
					LED=1;
				}
	}
	EXTI_ClearITPendingBit(EXTI_Line4);
}








13.myiic.h

#ifndef __MY_I2C_H__
#define __MY_I2C_H__
#include "stm32f4xx.h"

#define SCL_HIGH()  GPIO_SetBits(GPIOB,GPIO_Pin_6) //不能有空格,以免宏展开错误
#define SCL_LOW()  GPIO_ResetBits(GPIOB,GPIO_Pin_6)	
#define SDA_HIGH()	GPIO_SetBits(GPIOB,GPIO_Pin_7)
#define SDA_LOW()  GPIO_ResetBits(GPIOB,GPIO_Pin_7)


u8 IIC_Read_Byte(unsigned char ack);

void IIC_Send_Byte(u8 txd);

void IIC_NAck(void);

void IIC_Ack(void);

u8 IIC_Wait_Ack(void);

void IIC_Stop(void);

void IIC_Start(void);

void IIC_Init(void);

u8 READ_SDA(void);

void SDA_OUT(void);

void SDA_IN(void);
#endif

14. myiic.c

#include "myiic.h"
#include "delay.h"
#define  I2C_DELAY    8


void SDA_OUT(void)
{

	GPIO_InitTypeDef GPIO_InitStructure;
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
}

void SDA_IN(void)
{

	GPIO_InitTypeDef GPIO_InitStructure;
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
}
/*
//初始化IIC
I2C_SCL --->	PB6
I2C_SDA --->	PB7
*/
//1.初始化函数
void IIC_Init(void)
{			
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB时钟
	
	//GPIOB6,B7初始化设置
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
	//B组第6个引脚高电平 空闲状态
	//SCL_HIGH();
    SCL_HIGH();
	//B组第7个引脚高电平
	//SDA_HIGH();
    SDA_HIGH();
}

//2开始信号函数  ok
void IIC_Start(void)
{
	//B组第7个引脚设定成输出模式
	SDA_OUT(); 
	//两个都是输出高电平
	
     SDA_HIGH();

    SCL_HIGH();
	//延时2微秒
	delay_us(I2C_DELAY);
	//数据线由高电平变成低电平
	//START:when CLK is high,DATA change form high to low 
    SDA_LOW();
	//再延时2微秒
	delay_us(I2C_DELAY);
	//把时钟线也拉低
    SCL_LOW();
}	  

//3产生IIC停止信号
//STOP:when CLK is high DATA change form low to high
void IIC_Stop(void)
{
	//B组第7个引脚数据线设定成输出模式
	SDA_OUT();
	//两个都输出低电平。
    SCL_LOW();
     SDA_LOW();
 	delay_us(I2C_DELAY);
	//clk时钟线先跳到高电平。
    SCL_HIGH();
	delay_us(I2C_DELAY);
	//数据线再由低电平跳变到高电平。
    SDA_HIGH();
	delay_us(I2C_DELAY);							   	
}

//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	//将PB第7个引脚设定成输入模式,等待读取数据
	SDA_IN();
	//数据线高电平
	
    SDA_HIGH();
	delay_us(I2C_DELAY);
	//时钟线高电平

    SCL_HIGH();
	delay_us(I2C_DELAY);	
	//数据线和时钟线两个都是高电平
	//等待对面的从设备把数据线拉低。
	//然后就等待,while有等待的意思,读取第7个引脚的数据。
	while(READ_SDA()) 
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
//时钟输出0 	   
    SCL_LOW();
	return 0;  
} 


//产生ACK应答
//第9个时钟周期调用这个函数
void IIC_Ack(void)
{
	//低电平期间
     SCL_LOW();
	//数据线设定成输出模式
	SDA_OUT();
	//输出低电平   数据线始终为低电平
      SDA_LOW();
	//延时一定时间
	delay_us(I2C_DELAY);
	//输出高电平,并且稳定
     SCL_HIGH();
	delay_us(I2C_DELAY);
	//时钟线又跳到低电平:后续的电平可以变化
     SCL_LOW();
}


//不产生ACK应答		    
void IIC_NAck(void)
{
	//时钟线为低电平
	SCL_LOW() ;
	//设定数据线为输出模式
	SDA_OUT();
	//输出高电平 : 数据线始终为高电平
	SDA_HIGH();
	delay_us(I2C_DELAY);
	//时钟线跳变到高电平
	SCL_HIGH();
	delay_us(I2C_DELAY);
	//把时钟线拉低 
	SCL_LOW() ;
}				


//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
void IIC_Send_Byte(u8 txd) //1111 1111 & 1000 0000 
{                        
	u8 t;  
	//设定数据线为输出模式
	SDA_OUT(); 	  
	//拉低时钟开始数据传输
	SCL_LOW() ;
	for(t=0;t<8;t++)
	{  
		//取出数据的最高位 右移7位,然后发送出去
		
        if(txd & 0x80)
			SDA_HIGH();
		else
			SDA_LOW();
		//一个自己的数据左移一位,取出最高位
		txd<<=1;   
		//对TEA5767这三个延时都是必须的
		delay_us(I2C_DELAY);
		//高电平区间数据稳定
		SCL_HIGH();       
		delay_us(I2C_DELAY);
		//低电平期间,数据线数据可以变化
		SCL_LOW() ;	   
		delay_us(I2C_DELAY);
	}	 
} 	 

//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	//SDA设置为输入,数据线设定为输入模式
	SDA_IN();
	//循环读数据
	for(i=0;i<8;i++ )
	{
				//时钟线为低电平
			SCL_LOW() ; 
			delay_us(I2C_DELAY);
			//时钟线拉高
			SCL_HIGH();
			delay_us(I2C_DELAY);
			//时钟线为高电平的时候,读数据
			receive<<=1;		//receive是读到的是二进制数值
			if(READ_SDA()== 1)   //如果读到了数据就把receive++,
				receive++;    //读的是二进制数值
	}

    if (!ack)  
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}


u8 READ_SDA(void)
{
	u8 sda_val=0;
	sda_val=GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7);
	return sda_val;
}



15.oled.h

#ifndef __OLED_H__
#define __OLED_H__
#include "stm32f4xx.h"
//#include "sys.h"
/*
 OLED 屏 --I2C接口
  slave addr: 0x3C ,低7位
*/						
#define OLED_SLAVE_ADDR_WR   (0x3C<<1)   //从机地址 011 11000
extern   uint8_t HZ1[];  //湿
extern   uint8_t HZ2[];  //温
extern   uint8_t HZ3[];   //度
extern   uint8_t HZ4[];   // 欢
extern   uint8_t HZ5[];   //迎
extern   uint8_t HZ6[];   //来
extern   uint8_t HZ7[];   //到
extern   uint8_t HZ8[];   // 智
extern   uint8_t HZ9[];   //慧
extern   uint8_t HZ10[]; //农
extern   uint8_t HZ11[];  //业
//打开oled函数:初始化函数
void InitOLed(void);
//填充像素函数
void OLed_Fill(uint8_t bmp_data);
//显示字母函数
void OLed_ShowASCII(uint8_t x, uint8_t y,char *str);
//显示汉字函数
void OLed_ShowChina(uint8_t x,uint8_t y,uint8_t *buf);
//测试函数
void OLed_ShowTest(uint8_t x,uint8_t y);
//关闭oled函数
void offInitOLed(void);

//显示温度湿度
void OLed_ShowTemp(void);

#endif

16.oled.c

#include "stm32f4xx.h" //系统库文件
#include "oled.h"   //oled操作函数文件
#include "myiic.h"   //iic接口文件;

//======================================================
// 128X64I液晶底层驱动[8X16]字体库
// 设计者: powerint
// 描  述: [8X16]西文字符的字模数据 (纵向取模,字节倒序)
// !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
//======================================================

const unsigned char F8X16[]=
{
  
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0
  0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//!1
  0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//"2
  0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//#3
  0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$4
  0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//%5
  0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//&6
  0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//'7
  0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//(8
  0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//)9
  0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//*10
  0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+11
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//,12
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//-13
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//.14
  0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,///15
  0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//016
  0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//117
  0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//218
  0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//319
  0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//420
  0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//521
  0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//622
  0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//723
  0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//824
  0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//925
  0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//:26
  0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//;27
  0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//<28
  0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//=29
  0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//>30
  0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//?31
  0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@32
  0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A33
  0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B34
  0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C35
  0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D36
  0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E37
  0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F38
  0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G39
  0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H40
  0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I41
  0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J42
  0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K43
  0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L44
  0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M45
  0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N46
  0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O47
  0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P48
  0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q49
  0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R50
  0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S51
  0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T52
  0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U53
  0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V54
  0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W55
  0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X56
  0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y57
  0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z58
  0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[59
  0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\60
  0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//]61
  0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^62
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_63
  0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//`64
  0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a65
  0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b66
  0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c67
  0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d68
  0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e69
  0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f70
  0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g71
  0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h72
  0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i73
  0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j74
  0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k75
  0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l76
  0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m77
  0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n78
  0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o79
  0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p80
  0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q81
  0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r82
  0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s83
  0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t84
  0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u85
  0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v86
  0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w87
  0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x88
  0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y89
  0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z90
  0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{91
  0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//|92
  0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//}93
  0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~94
};

//汉字字模数据  字库字符数组

//温
uint8_t HZ1[]={
0x10,0x60,0x02,0x8C,0x00,0x00,0xFE,0x92,0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00,
0x04,0x04,0x7E,0x01,0x40,0x7E,0x42,0x42,0x7E,0x42,0x7E,0x42,0x42,0x7E,0x40,0x00,
};

//度
uint8_t HZ2[]={
0x00,0x00,0xFC,0x24,0x24,0x24,0xFC,0x25,0x26,0x24,0xFC,0x24,0x24,0x24,0x04,0x00,
0x40,0x30,0x8F,0x80,0x84,0x4C,0x55,0x25,0x25,0x25,0x55,0x4C,0x80,0x80,0x80,0x00,
};

//湿
uint8_t HZ3[]={
0x10,0x60,0x02,0x8C,0x00,0xFE,0x92,0x92,0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00,
0x04,0x04,0x7E,0x01,0x44,0x48,0x50,0x7F,0x40,0x40,0x7F,0x50,0x48,0x44,0x40,0x00,
};

uint8_t jj[] ={
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,
	
};


//;"欢",
uint8_t HZ4[] = {
0X04,0X24,0X44,0X84,0X64,0X9C,0X40,0X30,0X0F,0XC8,0X08,0X08,0X28,0X18,0X00,0X00,
0X10,0X08,0X06,0X01,0X82,0X4C,0X20,0X18,0X06,0X01,0X06,0X18,0X20,0X40,0X80,0X00,

};

//;"迎",
uint8_t HZ5[] = {
 0X40,0X40,0X42,0XCC,0X00,0X00,0XFC,0X04,0X02,0X00,0XFC,0X04,0X04,0XFC,0X00,0X00,
 0X00,0X40,0X20,0X1F,0X20,0X40,0X4F,0X44,0X42,0X40,0X7F,0X42,0X44,0X43,0X40,0X00,

};

//;"来",
uint8_t HZ6[] = {
 0X00,0X08,0X08,0X28,0XC8,0X08,0X08,0XFF,0X08,0X08,0X88,0X68,0X08,0X08,0X00,0X00,
 0X21,0X21,0X11,0X11,0X09,0X05,0X03,0XFF,0X03,0X05,0X09,0X11,0X11,0X21,0X21,0X00,

};

//;"到",
uint8_t HZ7[] = {
  0X42,0X62,0X52,0X4A,0XC6,0X42,0X52,0X62,0XC2,0X00,0XF8,0X00,0X00,0XFF,0X00,0X00,
	0X40,0XC4,0X44,0X44,0X7F,0X24,0X24,0X24,0X20,0X00,0X0F,0X40,0X80,0X7F,0X00,0X00,

};

//;"智",
uint8_t HZ8[] = {
 0X10,0X94,0X53,0X32,0X1E,0X32,0X52,0X10,0X00,0X7E,0X42,0X42,0X42,0X7E,0X00,0X00,
	0X00,0X00,0X00,0XFF,0X49,0X49,0X49,0X49,0X49,0X49,0X49,0XFF,0X00,0X00,0X00,0X00,

};

//;"慧",
uint8_t HZ9[] = {
  0X22,0X2A,0XAA,0XFF,0XAA,0XAA,0XA2,0X80,0XA2,0XAA,0XAA,0XFF,0XAA,0X2A,0X22,0X00,
	0X80,0X60,0X08,0X0A,0X6A,0X8A,0X8A,0X9A,0XAA,0X8A,0X8A,0XCA,0X0F,0X20,0XC0,0X00,

};

//;"农",
uint8_t HZ10[] = {
  0X20,0X18,0X08,0X08,0X08,0XC8,0X38,0XCF,0X08,0X08,0X08,0X08,0XA8,0X18,0X00,0X00,
	0X10,0X08,0X04,0X02,0XFF,0X40,0X20,0X00,0X03,0X04,0X0A,0X11,0X20,0X40,0X40,0X00,

};

//;"业",
uint8_t HZ11[] = {
  0X00,0X10,0X60,0X80,0X00,0XFF,0X00,0X00,0X00,0XFF,0X00,0X00,0XC0,0X30,0X00,0X00,
	0X40,0X40,0X40,0X43,0X40,0X7F,0X40,0X40,0X40,0X7F,0X42,0X41,0X40,0X40,0X40,0X00,

};


/*
 0X04,0X24,0X44,0X84,0X64,0X9C,0X40,0X30,0X0F,0XC8,0X08,0X08,0X28,0X18,0X00,0X00,0X10,0X08,0X06,0X01,0X82,0X4C,0X20,0X18,0X06,0X01,0X06,0X18,0X20,0X40,0X80,0X00;"欢",0
 0X40,0X40,0X42,0XCC,0X00,0X00,0XFC,0X04,0X02,0X00,0XFC,0X04,0X04,0XFC,0X00,0X00,0X00,0X40,0X20,0X1F,0X20,0X40,0X4F,0X44,0X42,0X40,0X7F,0X42,0X44,0X43,0X40,0X00;"迎",1
 0X00,0X08,0X08,0X28,0XC8,0X08,0X08,0XFF,0X08,0X08,0X88,0X68,0X08,0X08,0X00,0X00,0X21,0X21,0X11,0X11,0X09,0X05,0X03,0XFF,0X03,0X05,0X09,0X11,0X11,0X21,0X21,0X00;"来",2
 0X42,0X62,0X52,0X4A,0XC6,0X42,0X52,0X62,0XC2,0X00,0XF8,0X00,0X00,0XFF,0X00,0X00,0X40,0XC4,0X44,0X44,0X7F,0X24,0X24,0X24,0X20,0X00,0X0F,0X40,0X80,0X7F,0X00,0X00;"到",3
 0X10,0X94,0X53,0X32,0X1E,0X32,0X52,0X10,0X00,0X7E,0X42,0X42,0X42,0X7E,0X00,0X00,0X00,0X00,0X00,0XFF,0X49,0X49,0X49,0X49,0X49,0X49,0X49,0XFF,0X00,0X00,0X00,0X00;"智",4
 0X22,0X2A,0XAA,0XFF,0XAA,0XAA,0XA2,0X80,0XA2,0XAA,0XAA,0XFF,0XAA,0X2A,0X22,0X00,0X80,0X60,0X08,0X0A,0X6A,0X8A,0X8A,0X9A,0XAA,0X8A,0X8A,0XCA,0X0F,0X20,0XC0,0X00;"慧",5
 0X20,0X18,0X08,0X08,0X08,0XC8,0X38,0XCF,0X08,0X08,0X08,0X08,0XA8,0X18,0X00,0X00,0X10,0X08,0X04,0X02,0XFF,0X40,0X20,0X00,0X03,0X04,0X0A,0X11,0X20,0X40,0X40,0X00;"农",6
 0X00,0X10,0X60,0X80,0X00,0XFF,0X00,0X00,0X00,0XFF,0X00,0X00,0XC0,0X30,0X00,0X00,0X40,0X40,0X40,0X43,0X40,0X7F,0X40,0X40,0X40,0X7F,0X42,0X41,0X40,0X40,0X40,0X00;"业",7

*/
//显示温度 和湿度函数
void OLed_ShowTemp(void)
{
	//第1行显示温度
	OLed_ShowChina(16,0,HZ1);
	OLed_ShowChina(32,0,HZ2);
	OLed_ShowASCII(48,0,"111");  //显示英文。
	
	  //第2行显示湿度
	OLed_ShowChina(16,2,HZ3);
	OLed_ShowChina(32,2,HZ2);
}


/*
 写OLED命令寄存器的函数
*/
void WriteOLedCmd(uint8_t cmd)
{
	uint8_t CtrWord = 0x00;
	
	IIC_Start();
	
	IIC_Send_Byte(OLED_SLAVE_ADDR_WR); 	//发送从设备地址
	IIC_Wait_Ack();
	
	IIC_Send_Byte(CtrWord); //发送命令控制字
	IIC_Wait_Ack();
	
	IIC_Send_Byte(cmd);
	IIC_Wait_Ack();
	
	IIC_Stop();
}

/*
  写OLED数据的函数
*/

void WriteOLedData(uint8_t data)
{

	uint8_t CtrWord = 0x00;
	
	CtrWord |= (0x1<<6);  //表示发送的是数据	
	
	IIC_Start();

	IIC_Send_Byte(OLED_SLAVE_ADDR_WR); 	//发送从设备地址
	IIC_Wait_Ack();
	
	IIC_Send_Byte(CtrWord); //发送命令控制字
	IIC_Wait_Ack();
	
	IIC_Send_Byte(data);
	IIC_Wait_Ack();
	
	IIC_Stop();
}


/*
 设置显示位置
 y--> page address页地址  ,相当于 行 (0 ~ 7)       1 100
 x --> 列地址 (0 ~ 127)
*/
void OLed_SetPos(unsigned char x, unsigned char y)
{ 
	WriteOLedCmd((0xb0+y));  //设置行地址,设置页号
	WriteOLedCmd(((x&0xf0)>>4)|0x10);  //设置列地址高位
	WriteOLedCmd((x&0x0f)|0x00);   //设置列地址的低位
}


#define X_WIDTH   128

/*
 填充显示数据缓冲区
*/
void OLed_Fill(unsigned char bmp_data)
{
	unsigned char y,x;

	for(y=0;y<8;y++)  
	{
		  //设置PAGE地址
			WriteOLedCmd(0xb0+y); 
		  //设置列地址
			WriteOLedCmd(0x00);  
			WriteOLedCmd(0x10);
			
			for(x=0;x

17.myusart.h

#ifndef __MY_USART_H__
#define __MY_USART_H__
#include "stm32f4xx_rcc.h"
#define USART_REC_LEN 50

extern u8 USART_RX_BUF[USART_REC_LEN];//数据接收的数组
extern u16 USART_RX_STA;  //接受完成的标志  ,如果最高位是1 则接受完成

void myusart_init(int  usart_btl);//初始化
void printt(char str[],unsigned char num);//输出函数 串口传输函数

#endif


18.myusart.c

#include "myusart.h"
#include "stm32f4xx_usart.h"
#include "stm32f4xx_gpio.h"
#include "stdio.h"
#include "string.h"
#include "delay.h"
u8 USART_RX_BUF[USART_REC_LEN];
u16 USART_RX_STA = 0;  //接受完成的标志

char wendu[30] = "";
char str[128] = "\0";
char i = 0 ;


#pragma import(__use_no_semihosting)
//标准库需要的支持函数

struct __FILE
{
	int handle;
};

FILE __stdout;
//定义_sys_exit()以避免使用半主机模式    

void _sys_exit(int x)
{
	x=x;
}

int fputc(int ch,FILE *f)
{
	#if 0
	while( (USART1->SR&(1<<6))==0 ); //发送未完成等待
	USART1->DR = (unsigned char)ch;  //发送完成,那么可以向DR写入下一个待发送的数据	
	return ch;
	#else
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
	USART_SendData(USART1,(unsigned char)ch);	
	return ch;
	#endif
}

int fgetc(FILE *f)
{
	#if 0
	while((USART1->SR&(1<<5)) == 0);  //数据寄存器非空(即:接收到数据),那么跳出循环,否则一直等待
	return((int)(USART1->DR&0xff));	  //接收完成,读取数据。
	#else
	while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==RESET);
	return((int)(USART_ReceiveData(USART1)));
	#endif
}

void myusart_init(int  usart_btl)
{
    //第一步:准备三个结构体
    USART_InitTypeDef USART_InitStruct;  // 串口通信
    NVIC_InitTypeDef NVIC_InitStruct ;   // 中断寄存器NVIC
    GPIO_InitTypeDef GPIO_InitStruct;   //GPIO设置结构体
    
    //第二步: 时钟使能
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //串口时钟使能
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //GPIO口时钟使能
    
    //第三步: 设置端口复用
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9,GPIO_AF_USART1);
    //把A组中的10引脚设置成串口1模式(复用)
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10,GPIO_AF_USART1);
    //
    //第四步: 设置GPIO口的模式  (PA9 --TXD   PA10 ---RXD)
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF ; //复用功能
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA ,&GPIO_InitStruct);
    GPIO_SetBits(GPIOA,GPIO_Pin_9);
    
    /*GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init( GPIOA ,&GPIO_InitStruct);*/
    
    // 第五步: 设置usart寄存器
    USART_InitStruct.USART_BaudRate = usart_btl;  // 波特率
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 硬件流
    USART_InitStruct.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;  //允许接受和发送
    USART_InitStruct.USART_Parity = USART_Parity_No; // 奇偶校验位(无)
    USART_InitStruct.USART_StopBits = USART_StopBits_1;  //停止位 (1位)
    USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 字长 (8位)
    USART_Init(USART1,&USART_InitStruct);
     
    //第六步: 设置中断寄存器
    NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;   // 中断号
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;    //终端号使能
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; // 响应优先级
    NVIC_Init(&NVIC_InitStruct);
    
    //第七步: 设置接收中断使能   设置串口使能
    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //接收数据中断
    USART_Cmd(USART1,ENABLE);
    
}


//发送数据 aabcdef\r\n
//串口1中断服务程序
u8 count = 0;
void USART1_IRQHandler(void)                	
{

	u8 Res;
     //接收中断(接收到的数据必须是0x0d 0x0a结尾)
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) 
	{
		Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
		//printf("111");
		if((USART_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART_RX_STA&0x4000)//接收到了0x0d   0100 0000 0000 0000
			{
				if(Res!='\n')USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
			}
			else //还没收到‘\r’
			{	
				if(Res=='\r')USART_RX_STA|=0x4000;   //USART_RX_STA = 1100 0000 0000 0000
				else            //USART_RX_BUF[0] = 'd';  USART_RX_BUF[1] = 'a';..  USART_RX_BUF[4] = 'y'
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;        // danny\r\n   
					USART_RX_STA++;
                    //接收数据错误,重新开始接收	
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;  
				}		 
			}
		}   		 
  } 
} 



void printt(char str[],unsigned char num)
{
			unsigned char i = 0  ;
			for(i = 0 ; i < strlen(str);i++)
			{
				USART_SendData(USART1,str[i]);
				delay_ms(5);
			}
			//格式化函数,把十六进制转换成字符串
			sprintf(wendu,"%d",num);
			//添加一个换行符
			strcat(wendu,"\r\n");
			//串口打印函数
			for(i = 0 ; i < strlen(wendu);i++)
			{
				USART_SendData(USART1,wendu[i]);
				delay_ms(5);
			}		
}
//进行串口通信,当用户发送01+02  串口接受到后 发送03 给到pc

/*

SysTick_init(168);

    //中断分组
    u16 len = 0;
    int i = 0;
    SysTick_init(168);//初始化延时函数
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    myusart_init(115200);
		 
   while(1)
	{
        //数据接收完成
		if(USART_RX_STA&0x8000)
		{					   
			len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
			for(i=0;i

19. PWM.h 

#include "myusart.h"
#include "stm32f4xx_usart.h"
#include "stm32f4xx_gpio.h"
#include "stdio.h"
#include "string.h"
#include "delay.h"
u8 USART_RX_BUF[USART_REC_LEN];
u16 USART_RX_STA = 0;  //接受完成的标志

char wendu[30] = "";
char str[128] = "\0";
char i = 0 ;


#pragma import(__use_no_semihosting)
//标准库需要的支持函数

struct __FILE
{
	int handle;
};

FILE __stdout;
//定义_sys_exit()以避免使用半主机模式    

void _sys_exit(int x)
{
	x=x;
}

int fputc(int ch,FILE *f)
{
	#if 0
	while( (USART1->SR&(1<<6))==0 ); //发送未完成等待
	USART1->DR = (unsigned char)ch;  //发送完成,那么可以向DR写入下一个待发送的数据	
	return ch;
	#else
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
	USART_SendData(USART1,(unsigned char)ch);	
	return ch;
	#endif
}

int fgetc(FILE *f)
{
	#if 0
	while((USART1->SR&(1<<5)) == 0);  //数据寄存器非空(即:接收到数据),那么跳出循环,否则一直等待
	return((int)(USART1->DR&0xff));	  //接收完成,读取数据。
	#else
	while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==RESET);
	return((int)(USART_ReceiveData(USART1)));
	#endif
}

void myusart_init(int  usart_btl)
{
    //第一步:准备三个结构体
    USART_InitTypeDef USART_InitStruct;  // 串口通信
    NVIC_InitTypeDef NVIC_InitStruct ;   // 中断寄存器NVIC
    GPIO_InitTypeDef GPIO_InitStruct;   //GPIO设置结构体
    
    //第二步: 时钟使能
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //串口时钟使能
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //GPIO口时钟使能
    
    //第三步: 设置端口复用
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9,GPIO_AF_USART1);
    //把A组中的10引脚设置成串口1模式(复用)
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10,GPIO_AF_USART1);
    //
    //第四步: 设置GPIO口的模式  (PA9 --TXD   PA10 ---RXD)
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF ; //复用功能
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA ,&GPIO_InitStruct);
    GPIO_SetBits(GPIOA,GPIO_Pin_9);
    
    /*GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init( GPIOA ,&GPIO_InitStruct);*/
    
    // 第五步: 设置usart寄存器
    USART_InitStruct.USART_BaudRate = usart_btl;  // 波特率
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 硬件流
    USART_InitStruct.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;  //允许接受和发送
    USART_InitStruct.USART_Parity = USART_Parity_No; // 奇偶校验位(无)
    USART_InitStruct.USART_StopBits = USART_StopBits_1;  //停止位 (1位)
    USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 字长 (8位)
    USART_Init(USART1,&USART_InitStruct);
     
    //第六步: 设置中断寄存器
    NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;   // 中断号
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;    //终端号使能
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; // 响应优先级
    NVIC_Init(&NVIC_InitStruct);
    
    //第七步: 设置接收中断使能   设置串口使能
    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //接收数据中断
    USART_Cmd(USART1,ENABLE);
    
}


//发送数据 aabcdef\r\n
//串口1中断服务程序
u8 count = 0;
void USART1_IRQHandler(void)                	
{

	u8 Res;
     //接收中断(接收到的数据必须是0x0d 0x0a结尾)
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) 
	{
		Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
		//printf("111");
		if((USART_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART_RX_STA&0x4000)//接收到了0x0d   0100 0000 0000 0000
			{
				if(Res!='\n')USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
			}
			else //还没收到‘\r’
			{	
				if(Res=='\r')USART_RX_STA|=0x4000;   //USART_RX_STA = 1100 0000 0000 0000
				else            //USART_RX_BUF[0] = 'd';  USART_RX_BUF[1] = 'a';..  USART_RX_BUF[4] = 'y'
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;        // danny\r\n   
					USART_RX_STA++;
                    //接收数据错误,重新开始接收	
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;  
				}		 
			}
		}   		 
  } 
} 



void printt(char str[],unsigned char num)
{
			unsigned char i = 0  ;
			for(i = 0 ; i < strlen(str);i++)
			{
				USART_SendData(USART1,str[i]);
				delay_ms(5);
			}
			//格式化函数,把十六进制转换成字符串
			sprintf(wendu,"%d",num);
			//添加一个换行符
			strcat(wendu,"\r\n");
			//串口打印函数
			for(i = 0 ; i < strlen(wendu);i++)
			{
				USART_SendData(USART1,wendu[i]);
				delay_ms(5);
			}		
}
//进行串口通信,当用户发送01+02  串口接受到后 发送03 给到pc

/*

SysTick_init(168);

    //中断分组
    u16 len = 0;
    int i = 0;
    SysTick_init(168);//初始化延时函数
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    myusart_init(115200);
		 
   while(1)
	{
        //数据接收完成
		if(USART_RX_STA&0x8000)
		{					   
			len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
			for(i=0;i

20. PWM.c

#include "pwm.h"
#include "stm32f4xx.h"
#include "delay.h"

//TIM14 PWM部分初始化 
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM14_PWM_Init(void)
{		 					 
	//此部分需手动修改IO口设置	
	GPIO_InitTypeDef GPIO_InitStructure;
	//定时器结构体初始化。
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	//1TIM14时钟使能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);  	
	2使能PORTF时钟
	TIM_DeInit(TIM1);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); 		
	//3GPIOF9复用为定时器14                // Device header
	GPIO_PinAFConfig(GPIOE,GPIO_PinSource8,GPIO_AF_TIM1); 

	//GPIOF9
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;   
	//复用功能
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  
	//速度100MHz
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;  
	//推挽复用输出
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;   
	//上拉
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;  
	//4初始化PF9
	GPIO_Init(GPIOE,&GPIO_InitStructure);              
	  
	TIM_TimeBaseStructure.TIM_Prescaler=400;  //定时器分频
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseStructure.TIM_Period=100;   //自动重装载值
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
//	TIM_TimeBaseStructure.TIM_RepetitionCounter = 1; 
	//5初始化定时器14
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
	
	//初始化TIM14 Channel1 PWM模式	
	//选择定时器模式:TIM脉冲宽度调制模式2
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 	        
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
	//6根据T指定的参数初始化外设TIM1 4OC1
//	TIM_OCInitStructure.TIM_Pulse = 100;
	TIM_OC1Init(TIM1, &TIM_OCInitStructure); 
  
	//7使能TIM14在CCR1上的预装载寄存器
//	TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  
//	//8ARPE使能 
//	TIM_ARRPreloadConfig(TIM1,ENABLE);
	//9使能TIM14
	TIM_Cmd(TIM1, ENABLE);  	
	TIM_CtrlPWMOutputs(TIM1, ENABLE);		
}  

void ppp(int a)// 呼吸灯
{
		static u16 led0pwmval=0;    
		if(a<0)
		{
			led0pwmval=0;
		}
		else if(a>=100)
		{
			led0pwmval=100;
		}
		else
		{
			led0pwmval =a;
		}
		//修改比较值,修改占空比	
		TIM_SetCompare1(TIM1,led0pwmval);

}


21.wwdg.h

#ifndef __WWDG_H__
#define __WWDG_H__

void wwdginit(void);//窗口看门狗初始化

#endif

22.wwdg.c

#include "stm32f4xx.h"
#include "wwdg.h"
#include "delay.h"
#include "misc.h"


//当前值寄存器从自定义  0x7f 递减
//0x5f:自定的窗口上限值
//0x3f:固定的串口下限值
//只有窗口期才可以喂狗,如果喂狗,系统就不会重启,否则,如果没有配置中断功能,程序就会重启。
//如果窗口期没有喂狗,自动进入到中断函数中。可以在中断函数中进行喂狗。

//窗口看门狗可以配置中断。
void wwdginit()
{
		//1.配置时钟
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
	
		//2设置分频值:WWDG_Prescaler_8
		WWDG_SetPrescaler(WWDG_Prescaler_8);
	
		//3设置窗口值 : 窗口上限值。只要比 0x3f大就行。
		WWDG_SetWindowValue(0x6F); 
	
		//4.开启看门狗
		WWDG_Enable(0x7F);
	
		//5.配置窗口看门狗中断类型
		NVIC_InitTypeDef wwdgstruct;
		wwdgstruct.NVIC_IRQChannel= WWDG_IRQn;  
		 //抢占优先级为2
		wwdgstruct.NVIC_IRQChannelPreemptionPriority=0x00; 
		wwdgstruct.NVIC_IRQChannelSubPriority=0x00;	
		//子优先级为3
		wwdgstruct.NVIC_IRQChannelCmd=ENABLE;  
		//使能窗口看门狗中断
		NVIC_Init(&wwdgstruct);
		
		//6清除提前唤醒中断标志位:防止提前进入中断函数中。
		WWDG_ClearFlag();
	
		//7开启中断函数使能.让窗口看门狗可以使用中断功能
		WWDG_EnableIT();
}
//窗口看门狗中断函数一定是这个。

//1.有没有进入中断函数中  ok
//2.为什么一直重启? 时间问题。
void WWDG_IRQHandler(void)
{
			//重设窗口看门狗值 喂狗 防止重启
	WWDG_SetCounter(0x5f); //0x7f  - 0x3f   :   0x5f - 0x3f ;   
			//清除提前唤醒中断标志位
	WWDG_ClearFlag();
			//喂狗的数值一定要在窗口期内:一定要在5f - 3f之间
}





上位机的系统文件

 23. delay.h

#ifndef __DELAY_H
#define __DELAY_H 			   
#include 	  

// 	 
void delay_init(u8 SYSCLK);
void delay_ms(u16 nms);
void delay_us(u32 nus);

#endif





























24.delay.c

#include "delay.h"
#include "sys.h"
#include "misc.h"
// 	 
//如果使用OS,则包括下面的头文件(以ucos为例)即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//支持OS时,使用	  
#endif
//  

//********************************************************************************

// 

static u8  fac_us=0;							//us延时倍乘数			   
static u16 fac_ms=0;							//ms延时倍乘数,在os下,代表每个节拍的ms数
	
#if SYSTEM_SUPPORT_OS							//如果SYSTEM_SUPPORT_OS定义了,说明要支持OS了(不限于UCOS).
//当delay_us/delay_ms需要支持OS的时候需要三个与OS相关的宏定义和函数来支持
//首先是3个宏定义:
//    delay_osrunning:用于表示OS当前是否正在运行,以决定是否可以使用相关函数
//delay_ostickspersec:用于表示OS设定的时钟节拍,delay_init将根据这个参数来初始哈systick
// delay_osintnesting:用于表示OS中断嵌套级别,因为中断里面不可以调度,delay_ms使用该参数来决定如何运行
//然后是3个函数:
//  delay_osschedlock:用于锁定OS任务调度,禁止调度
//delay_osschedunlock:用于解锁OS任务调度,重新开启调度
//    delay_ostimedly:用于OS延时,可以引起任务调度.

//本例程仅作UCOSII和UCOSIII的支持,其他OS,请自行参考着移植
//支持UCOSII
#ifdef 	OS_CRITICAL_METHOD						//OS_CRITICAL_METHOD定义了,说明要支持UCOSII				
#define delay_osrunning		OSRunning			//OS是否运行标记,0,不运行;1,在运行
#define delay_ostickspersec	OS_TICKS_PER_SEC	//OS时钟节拍,即每秒调度次数
#define delay_osintnesting 	OSIntNesting		//中断嵌套级别,即中断嵌套次数
#endif

//支持UCOSIII
#ifdef 	CPU_CFG_CRITICAL_METHOD					//CPU_CFG_CRITICAL_METHOD定义了,说明要支持UCOSIII	
#define delay_osrunning		OSRunning			//OS是否运行标记,0,不运行;1,在运行
#define delay_ostickspersec	OSCfg_TickRate_Hz	//OS时钟节拍,即每秒调度次数
#define delay_osintnesting 	OSIntNestingCtr		//中断嵌套级别,即中断嵌套次数
#endif


//us级延时时,关闭任务调度(防止打断us级延迟)
void delay_osschedlock(void)
{
#ifdef CPU_CFG_CRITICAL_METHOD   			//使用UCOSIII
	OS_ERR err; 
	OSSchedLock(&err);						//UCOSIII的方式,禁止调度,防止打断us延时
#else										//否则UCOSII
	OSSchedLock();							//UCOSII的方式,禁止调度,防止打断us延时
#endif
}

//us级延时时,恢复任务调度
void delay_osschedunlock(void)
{	
#ifdef CPU_CFG_CRITICAL_METHOD   			//使用UCOSIII
	OS_ERR err; 
	OSSchedUnlock(&err);					//UCOSIII的方式,恢复调度
#else										//否则UCOSII
	OSSchedUnlock();						//UCOSII的方式,恢复调度
#endif
}

//调用OS自带的延时函数延时
//ticks:延时的节拍数
void delay_ostimedly(u32 ticks)
{
#ifdef CPU_CFG_CRITICAL_METHOD
	OS_ERR err; 
	OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err);//UCOSIII延时采用周期模式
#else
	OSTimeDly(ticks);						//UCOSII延时
#endif 
}
 
//systick中断服务函数,使用OS时用到
void SysTick_Handler(void)
{	
	if(delay_osrunning==1)					//OS开始跑了,才执行正常的调度处理
	{
		OSIntEnter();						//进入中断
		OSTimeTick();       				//调用ucos的时钟服务程序               
		OSIntExit();       	 				//触发任务切换软中断
	}
}
#endif
			   
//初始化延迟函数
//当使用OS的时候,此函数会初始化OS的时钟节拍
//SYSTICK的时钟固定为AHB时钟的1/8
//SYSCLK:系统时钟频率
void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS 						//如果需要支持OS.
	u32 reload;
#endif
 	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); 
	fac_us=SYSCLK/8;						//不论是否使用OS,fac_us都需要使用
#if SYSTEM_SUPPORT_OS 						//如果需要支持OS.
	reload=SYSCLK/8;						//每秒钟的计数次数 单位为M	   
	reload*=1000000/delay_ostickspersec;	//根据delay_ostickspersec设定溢出时间
											//reload为24位寄存器,最大值:16777216,在168M下,约合0.7989s左右	
	fac_ms=1000/delay_ostickspersec;		//代表OS可以延时的最少单位	   
	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;   	//开启SYSTICK中断
	SysTick->LOAD=reload; 					//每1/delay_ostickspersec秒中断一次	
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; 	//开启SYSTICK    
#else
	fac_ms=(u16)fac_us*1000;				//非OS下,代表每个ms需要的systick时钟数   
#endif
}								    

#if SYSTEM_SUPPORT_OS 						//如果需要支持OS.
//延时nus
//nus:要延时的us数.	
//nus:0~204522252(最大值即2^32/fac_us@fac_us=21)	    								   
void delay_us(u32 nus)
{		
	u32 ticks;
	u32 told,tnow,tcnt=0;
	u32 reload=SysTick->LOAD;				//LOAD的值	    	 
	ticks=nus*fac_us; 						//需要的节拍数 
	delay_osschedlock();					//阻止OS调度,防止打断us延时
	told=SysTick->VAL;        				//刚进入时的计数器值
	while(1)
	{
		tnow=SysTick->VAL;	
		if(tnow!=told)
		{	    
			if(tnow=ticks)break;			//时间超过/等于要延迟的时间,则退出.
		}  
	};
	delay_osschedunlock();					//恢复OS调度											    
}  
//延时nms
//nms:要延时的ms数
//nms:0~65535
void delay_ms(u16 nms)
{	
	if(delay_osrunning&&delay_osintnesting==0)//如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度)	    
	{		 
		if(nms>=fac_ms)						//延时的时间大于OS的最少时间周期 
		{ 
   			delay_ostimedly(nms/fac_ms);	//OS延时
		}
		nms%=fac_ms;						//OS已经无法提供这么小的延时了,采用普通方式延时    
	}
	delay_us((u32)(nms*1000));				//普通方式延时
}
#else  //不用ucos时
//延时nus
//nus为要延时的us数.	
//注意:nus的值,不要大于798915us(最大值即2^24/fac_us@fac_us=21)
void delay_us(u32 nus)
{		
	u32 temp;	    	 
	SysTick->LOAD=nus*fac_us; 				//时间加载	  		 
	SysTick->VAL=0x00;        				//清空计数器
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数 	 
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));	//等待时间到达   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
	SysTick->VAL =0X00;       				//清空计数器 
}
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对168M条件下,nms<=798ms 
void delay_xms(u16 nms)
{	 		  	  
	u32 temp;		   
	SysTick->LOAD=(u32)nms*fac_ms;			//时间加载(SysTick->LOAD为24bit)
	SysTick->VAL =0x00;           			//清空计数器
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;          //开始倒数 
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));	//等待时间到达   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       //关闭计数器
	SysTick->VAL =0X00;     		  		//清空计数器	  	    
} 
//延时nms 
//nms:0~65535
void delay_ms(u16 nms)
{	 	 
	u8 repeat=nms/540;						//这里用540,是考虑到某些客户可能超频使用,
											//比如超频到248M的时候,delay_xms最大只能延时541ms左右了
	u16 remain=nms%540;
	while(repeat)
	{
		delay_xms(540);
		repeat--;
	}
	if(remain)delay_xms(remain);
} 
#endif
			 




































25. sys.h

#ifndef __SYS_H
#define __SYS_H	 
#include "stm32f4xx.h" 
//	 

// 


//0,不支持ucos
//1,支持ucos
#define SYSTEM_SUPPORT_OS		0		//定义系统文件夹是否支持UCOS
																	    
	 
//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<>第五章(87页~92页).M4同M3类似,只是寄存器地址变了.
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+20) //0x40020014
#define GPIOB_ODR_Addr    (GPIOB_BASE+20) //0x40020414 
#define GPIOC_ODR_Addr    (GPIOC_BASE+20) //0x40020814 
#define GPIOD_ODR_Addr    (GPIOD_BASE+20) //0x40020C14 
#define GPIOE_ODR_Addr    (GPIOE_BASE+20) //0x40021014 
#define GPIOF_ODR_Addr    (GPIOF_BASE+20) //0x40021414    
#define GPIOG_ODR_Addr    (GPIOG_BASE+20) //0x40021814   
#define GPIOH_ODR_Addr    (GPIOH_BASE+20) //0x40021C14    
#define GPIOI_ODR_Addr    (GPIOI_BASE+20) //0x40022014     

#define GPIOA_IDR_Addr    (GPIOA_BASE+16) //0x40020010 
#define GPIOB_IDR_Addr    (GPIOB_BASE+16) //0x40020410 
#define GPIOC_IDR_Addr    (GPIOC_BASE+16) //0x40020810 
#define GPIOD_IDR_Addr    (GPIOD_BASE+16) //0x40020C10 
#define GPIOE_IDR_Addr    (GPIOE_BASE+16) //0x40021010 
#define GPIOF_IDR_Addr    (GPIOF_BASE+16) //0x40021410 
#define GPIOG_IDR_Addr    (GPIOG_BASE+16) //0x40021810 
#define GPIOH_IDR_Addr    (GPIOH_BASE+16) //0x40021C10 
#define GPIOI_IDR_Addr    (GPIOI_BASE+16) //0x40022010 
 
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入

#define PHout(n)   BIT_ADDR(GPIOH_ODR_Addr,n)  //输出 
#define PHin(n)    BIT_ADDR(GPIOH_IDR_Addr,n)  //输入

#define PIout(n)   BIT_ADDR(GPIOI_ODR_Addr,n)  //输出 
#define PIin(n)    BIT_ADDR(GPIOI_IDR_Addr,n)  //输入

//以下为汇编函数
void WFI_SET(void);		//执行WFI指令
void INTX_DISABLE(void);//关闭所有中断
void INTX_ENABLE(void);	//开启所有中断
void MSR_MSP(u32 addr);	//设置堆栈地址 
#endif











26.sys.c

#include "sys.h"  
//	 

//  


//THUMB指令不支持汇编内联
//采用如下方法实现执行汇编指令WFI  
__asm void WFI_SET(void)
{
	WFI;		  
}
//关闭所有中断(但是不包括fault和NMI中断)
__asm void INTX_DISABLE(void)
{
	CPSID   I
	BX      LR	  
}
//开启所有中断
__asm void INTX_ENABLE(void)
{
	CPSIE   I
	BX      LR  
}
//设置栈顶地址
//addr:栈顶地址
__asm void MSR_MSP(u32 addr) 
{
	MSR MSP, r0 			//set Main Stack value
	BX r14
}


















下位机程序

27.  ui 界面代码:



 MainWindow
 
  
   
    0
    0
    1079
    499
   
  
  
   MainWindow
  
  
   
    
     
      11
      11
      469
      374
     
    
    
     Qt::Horizontal
    
    
     
      串口控制
     
     
      
       
        
         
          
           串口号
          
         
        
        
         
        
       
      
      
       
        
         
          
           波特率
          
         
        
        
         
          
           
            9600
           
          
          
           
            115200
           
          
         
        
       
      
      
       
        
         
          
           数据位
          
         
        
        
         
          
           
            8
           
          
         
        
       
      
      
       
        
         
          
           校验位
          
         
        
        
         
          
           
            无校验
           
          
         
        
       
      
      
       
        
         
          
           停止位
          
         
        
        
         
          
           
            1
           
          
         
        
       
      
      
       
        
         打开串口
        
       
      
      
       
        
         打开小灯
        
       
      
      
       
        
         打开蜂鸣器
        
       
      
      
       
        
         获取温湿度数据
        
       
      
     
    
    
     
      false
     
     
      串口数据
     
     
      
       
        
         接收数据
        
        
         
          
         
        
       
      
      
       
        
         发送数据
        
        
         
          
           
            
             
              内容:
             
            
           
           
            
             
              发送
             
            
           
          
         
         
          
         
        
       
      
     
    
   
   
    
     
      490
      0
      251
      381
     
    
   
   
    
     
      850
      120
      171
      201
     
    
   
  
  
   
    
     0
     0
     1079
     26
    
   
  
  
 
 
 

28. mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
/***** 串口模块 ******/
#include  //串口类
#include  //串口属性类 { 获取系统可用的串口 }
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
public:
    void GetSystenSerilPort(); /*** 获取系统可用串口列表,并打印到UI界面 ***/
private:
    Ui::MainWindow *ui;
    QSerialPort *SerialPort; /** 串口类 **/
    QString data11;
public slots:
    void slot_pushButton_open();
    void slot_pushButton_send();
    void slot_SerialPort_readyRead();
private slots:
    void on_pushButton_led_clicked();
    void on_pushButton_beep_clicked();
    void on_pushButton_clicked();
    void on_dial_valueChanged(int value);
};

#endif // MAINWINDOW_H

29. mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include 
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    /*** 申请串口类对象空间 ****/
    SerialPort = new QSerialPort(this);
    /*** 类构造时就获取系统可用串口列表 ***/
    GetSystenSerilPort();

    /*** 连接槽函数 ****/
    connect(ui->pushButton_open,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_open()));
    connect(SerialPort,SIGNAL(readyRead()),this,SLOT(slot_SerialPort_readyRead()));
    connect(ui->pushButton_send,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_send()));
}

void MainWindow::slot_pushButton_send()
{
    QString text = ui->lineEdit_send->text();

    SerialPort->write(text.toUtf8());
}


void MainWindow::slot_SerialPort_readyRead()
{
    QByteArray data = SerialPort->readAll();
    ui->textBrowser_read->append(data);
    QString a= QString(data);
    if(a=="\r"  || a=="\n")
    {
        data11.clear();
        return;
    }
    data11+=a;


    if(data11.size()>=7)
    {
        ui->listWidget->clear();
        ui->listWidget->addItem(data11);
        data11=data11.right(2);
        QString kk=QString("温度: ")+data11;
        ui->listWidget->addItem(kk);
        data11.clear();
    }

}


#include  /*** 标准对话框 ****/
void MainWindow::slot_pushButton_open()
{
    /******* 设置串口属性 ******/
    SerialPort->setPortName(ui->comboBox_portName->currentText()); //设置串口号
    SerialPort->setBaudRate(ui->comboBox_BaudRate->currentText().toInt()); //设置波特率
    if(ui->comboBox_DataBits->currentText() == "8"){
        SerialPort->setDataBits(QSerialPort::Data8); //设置数据位为8位
    }
    if(ui->comboBox_Parity->currentText() == "无校验"){
        SerialPort->setParity(QSerialPort::NoParity); //设置校验位为无校验
    }

    if(ui->comboBox_StopBits->currentText() == "1"){
        SerialPort->setStopBits(QSerialPort::OneStop); //设置停止位为1位
    }
    /***** 打开串口 ****/
    bool ok = false;
    if(ui->pushButton_open->text() == "打开串口")
    {
        ok = SerialPort->open(QIODevice::ReadWrite);
        if(ok == true) //串口打开成功
        {
            ui->groupBox_data->setEnabled(true);
            ui->pushButton_open->setText("关闭串口");
        }
        else
        {
            QMessageBox::warning(this,"警告","串口打开失败,请检查串口参数或串口已被占用");
            return ;
        }
    }else
    {
        SerialPort->close(); //关闭串口
        ui->pushButton_open->setText("打开串口");
        ui->groupBox_data->setEnabled(false);
    }
}




MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::GetSystenSerilPort()
{
    QList list_SerialPortInfo = QSerialPortInfo::availablePorts(); /*** 获取系统可用串口列表 ***/

    ui->comboBox_portName->clear(); /** 清空 串口号的下拉选项框 ***/
    for(QSerialPortInfo value : list_SerialPortInfo)
    {
        ui->comboBox_portName->addItem(value.portName()); /*** 将串口名称添加到 UI 的串口号下拉选项框中 ***/
    }
}



void MainWindow::on_pushButton_led_clicked()//打开小灯
{
    if(ui->pushButton_led->text() == "打开小灯")
    {
         qDebug()<<"打开小灯发送成功";
         ui->pushButton_led->setText("关闭小灯");
          QString text=QString("1\r\n");
          SerialPort->write(text.toLocal8Bit());
    }
    else
    {
         qDebug()<<"关闭小灯发送成功";
        ui->pushButton_led->setText("打开小灯");
        QString text=QString("2\r\n");
       SerialPort->write(text.toLocal8Bit());
    }

}

void MainWindow::on_pushButton_beep_clicked()//打开蜂鸣器
{
    if(ui->pushButton_beep->text() == "打开蜂鸣器")
    {
         qDebug()<<"打开蜂鸣器发送成功";
         ui->pushButton_beep->setText("关闭蜂鸣器");
         QString text=QString("3\r\n");
         SerialPort->write(text.toLocal8Bit());
    }
    else
    {
        qDebug()<<"关闭蜂鸣器发送成功";
        QString text=QString("4\r\n");
        SerialPort->write(text.toLocal8Bit());
        ui->pushButton_beep->setText("打开蜂鸣器");
    }

}


void MainWindow::on_pushButton_clicked()//获取温湿度
{
    qDebug()<<"获取温湿度发送成功";
    QString text=QString("5\r\n");
    SerialPort->write(text.toLocal8Bit());

}

void MainWindow::on_dial_valueChanged(int value)
{
    qDebug()<<"旋钮转动";
    QString text=QString("0") + QString::number(value) + QString("\r\n");
    SerialPort->write(text.toLocal8Bit());
}

mian.cpp

#include "mainwindow.h"

#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

你可能感兴趣的:(个人项目专栏,stm32,单片机,嵌入式硬件)