zoukankan      html  css  js  c++  java
  • STM32 f407 温湿度采集报警

    软件

    keil5

    实现

    1.使用stm32f407中的DS18B20传感器采集空气温度
    2.使用stm32f407中的DHT11传感器采集空气的温度和湿度
    3.显示到stm32f407的LCD液晶显示器上
    4.当温度超过30℃时,led灯 和 电磁继电器控制的灯闪烁,蜂鸣器持续响
    5.当温度低于30℃时,一切恢复

    效果

    效果

    源码

    main.c

    #include "led.h"
    #include "button.h"
    #include "buzzer.h"
    #include "delay.h"
    #include "lcd.h"
    #include "ds18b20.h"
    #include "dht11.h"
    
    #define WAR_T 30
    
    int main(void)    {	
    	int yan;
    	char buf[10];
    	char dht[5];
    	delay_init();
    	LCD_Init();
    	buzzer_init();
    	//320 * 240
    	DS18B20_Init();
    	dht_init();
    	LCD_Clear(0x01CF);
    	BRUSH_COLOR = WHITE;
    	BACK_COLOR = 0x1f << 11;
    	//BACK_COLOR = BLACK;
    	//LCD_DisplayString(30, 50, 24, (u8 *)" 0.0 ");
    	LCD_DisplayMyname(10,200);		//Ãû×Ö
    	LCD_Draw_Rectangle(1, 1, 318, 238);
    	LCD_Draw_Line( 110,1 ,110 ,160 );
    	LCD_Draw_Line( 220,1 ,220 ,160 );
    	LCD_Draw_Line( 1,120 ,220 ,120 );
    	LCD_Draw_Line( 1,160 ,318 ,160 );
    	
    	LCD_DisplayString(10, 70, 16, (u8 *)"PM2.5 ug/m3");
    	LCD_DisplayString(125, 70, 16, (u8 *)"HCHO mg/m3");
    	LCD_DisplayString(260, 170, 24, (u8 *)"TIME");
    	LCD_DisplayString(220, 200, 24, (u8 *)"12 : 00");
    	LCD_DisplayString(30, 175, 24, (u8 *)"WELCOME !");
    	
    	LCD_DisplayTu1(225,20);
    	LCD_DisplayTu2(225,100);
    	
    	//for(yan=0xF800;yan<=0xFFE0;yan++);
    	LCD_Draw_Rectangle(10, 90, 90, 100);
    	LCD_Draw_Rectangle(125, 90, 210, 100);
    	LCD_Fill_onecolor(10, 95, 90, 100,yan);
    	LCD_Fill_onecolor(125, 95, 210, 100,yan);
    	
    	while(1)	{
    		int i;
    		get_temperature(buf);
    		LCD_DisplayString(225, 50, 24, (u8 *)buf);
    		LCD_DisplayOTherChar(295,50,0,24);//温度符号
    		dht_get_data(dht);
    		LCD_DisplayNum(285, 100, dht[0], 2, 24, 0);
    		LCD_DisplayNum(285, 20, dht[2], 2, 24, 0);
    		//if( buf[1] >= '0'+2 && buf[2] >= 9+'0')
    
    		delay_ms(500);
    	}
    }
    

    led.h

    #ifndef __LED_H
    #define __LED_H
    
    #include "stm32f4xx_conf.h"
    
    /*
    	LED0	PE3
    	LED1	PE4
    	LED2	PG9
    	GPIO管脚输出高电压时灯灭 低电压时亮
    	1.对于GPIO管脚打开时钟
    */
    
    #define GPIOE_MODER		(*(volatile unsigned int *)(GPIOE_BASE + 0x00))
    #define GPIOE_OTYPER	(*(volatile unsigned int *)(GPIOE_BASE + 0x04))
    #define GPIOE_OSPEEDR	(*(volatile unsigned int *)(GPIOE_BASE + 0x08))
    #define GPIOE_PUPDR		(*(volatile unsigned int *)(GPIOE_BASE + 0x0C))
    #define GPIOE_ODR		(*(volatile unsigned int *)(GPIOE_BASE + 0x14))
    
    #define GPIOG_MODER	(*(volatile unsigned int *)(GPIOG_BASE + 0x00))
    #define GPIOG_OTYPER	(*(volatile unsigned int *)(GPIOG_BASE + 0x04))
    #define GPIOG_OSPEEDR	(*(volatile unsigned int *)(GPIOG_BASE + 0x08))
    #define GPIOG_PUPDR		(*(volatile unsigned int *)(GPIOG_BASE + 0x0C))
    #define GPIOG_ODR		(*(volatile unsigned int *)(GPIOG_BASE + 0x14))
    
    extern void led_init(void);
    extern void led_on(int no);
    extern void led_off(int no);
    #endif
    

    led.c

    #include "led.h"
    #include "bitband.h"
    
    void led_init(void)    {
    	GPIO_InitTypeDef LED;
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOG, ENABLE);
    	
    	LED.GPIO_Mode = GPIO_Mode_OUT;
    	LED.GPIO_OType = GPIO_OType_PP;
    	LED.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4;
    	LED.GPIO_PuPd = GPIO_PuPd_NOPULL;
    	LED.GPIO_Speed = GPIO_Fast_Speed;
    	
    	GPIO_Init(GPIOE, &LED);
    	LED.GPIO_Pin = GPIO_Pin_9;
    	GPIO_Init(GPIOG, &LED);
    	GPIO_SetBits(GPIOE, GPIO_Pin_3 | GPIO_Pin_4);
    	GPIO_SetBits(GPIOG, GPIO_Pin_9);
    }
    
    void led_on(int no)    {
    	switch(no)	{
    		case 0 :
    			PGOut(9) = 0;
    			break;
    		case 1 :
    			PEOut(4) = 0;
    			break;
    		case 2 :
    			PEOut(3) = 0;
    			break;
    		default:
    			break;
    	}
    }
    
    void led_off(int no)    {
    	switch(no)	{
    		case 0 :
    			PGOut(9) = 1;
    			break;
    		case 1 :
    			PEOut(4) = 1;
    			break;
    		case 2 :
    			PEOut(3) = 1;
    			break;
    		default:
    			break;
    	}
    }
    

    button.h

    #ifndef __BUTTON_H
    #define __BUTTON_H
    
    #include "stm32f4xx_conf.h"
    
    extern void button_init(void);
    extern int button_state(int);
    
    #endif
    

    button.c

    #include "button.h"
    #include "bitband.h"
    // PF9 PF8 PF7 PE6
    //按键按下是1 抬起是0
    void button_init(void)    {
    	GPIO_InitTypeDef BUTTON;
    	
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF, ENABLE);
    	
    	BUTTON.GPIO_Mode = GPIO_Mode_IN;
    	BUTTON.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
    	BUTTON.GPIO_PuPd = GPIO_PuPd_NOPULL;
    	
    	GPIO_Init(GPIOF, &BUTTON);
    	
    	BUTTON.GPIO_Pin = GPIO_Pin_6;
    	GPIO_Init(GPIOE, &BUTTON);
    }
    
    int button_state(int no)    {
    	int ret;
    	
    	switch(no)	{
    		case 0 : 
    			ret = PFIn(9);
    			break;
    		case 1 :
    			ret = PFIn(8);
    			break;
    		case 2 :
    			ret = PFIn(7);
    			break;
    		case 3 :
    			ret = PEIn(6);
    			break;
    		default:
    			ret = 1;
    			break;
    	}	return !ret;
    }
    

    buzzer.h

    #ifndef __BUZZER_H
    #define __BUZZER_H
    
    #include "stm32f4xx_conf.h"
    
    extern void buzzer_init(void);
    extern void buzzer_on(void);
    extern void buzzer_off(void);
    
    #endif
    

    buzzer.c

    #include "buzzer.h"
    #include "bitband.h"
    //pd7
    void buzzer_init(void)    {
    	GPIO_InitTypeDef BUZZER;
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
    	
    	BUZZER.GPIO_Mode = GPIO_Mode_OUT;
    	BUZZER.GPIO_OType = GPIO_OType_PP;
    	BUZZER.GPIO_Pin = GPIO_Pin_7;
    	BUZZER.GPIO_PuPd = GPIO_PuPd_NOPULL;
    	BUZZER.GPIO_Speed = GPIO_Fast_Speed;
    	
    	GPIO_Init(GPIOD, &BUZZER);
    	GPIO_ResetBits(GPIOD, GPIO_Pin_7);
    }
    
    void buzzer_on(void)    {
    	PDOut(7) = 1;
    }
    
    void buzzer_off(void)    {
    	PDOut(7) = 0;
    }
    

    delay.h

    #ifndef __DELAY_H
    #define __DELAY_H 			   
    #include "stm32f4xx.h" 
    
    typedef uint32_t  u32;
    typedef uint16_t  u16;
    typedef uint8_t   u8;
    
    #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)) 
    
    //GPIO
    #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     
    //GPIO
    #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 
     
    #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)  
    
    #define SYSCLK 168    //调用系统时钟
    	
    void delay_init(void);
    void delay_ms(u16 nms);
    void delay_us(u32 nus);
    #endif
    

    delay.c

    #include "delay.h"
    
    //利用系统定时,编写的延时函数
    static u8  fac_us=0; //us延时倍乘数			   
    static u16 fac_ms=0; //ms延时倍乘数,在ucos下,代表每个街拍的ms数
    
    /****************************************************************************
    * 名称: delay_init()
    *功能:延时函数初始化
    * 入口参数:无
    * 返回参数:无
    ****************************************************************************/
    void delay_init()    {
     	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
    	fac_us=SYSCLK/8;
    	fac_ms=(u16)fac_us*1000; //每个ms需要的systick时钟数
    }								    
    
    /****************************************************************************
    * 名称: void delay_us(u32 nus)
    * 功能:延时nus
    * 入口参数:要延时的微秒数
    * 返回参数:无
    * 说明:nus的值 不要大于798915us
    ****************************************************************************/
    void delay_us(u32 nus)    {		
    	u32 midtime;	    	 
    	SysTick->LOAD=nus*fac_us; //时间加载		 
    	SysTick->VAL=0x00;        //清空计数器
    	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;          //开始倒数
    	do	{
    		midtime=SysTick->CTRL;
    	}
    	while((midtime&0x01)&&!(midtime&(1<<16)));//等待时间到达 
    	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       //关闭计数器
    	SysTick->VAL =0X00;       //清空计数器 
    }
    /****************************************************************************
    * 名称: void delay_xms(u16 nms)
    * 功能:延时nms
    * 入口参数:要延时的毫秒数
    * 返回参数:无
    * 说明:SysTick->LOAD为24位寄存器,所以,最大延时为:nms<=0xffffff*8*1000/SYSCLK
                对168M条件下nms<=798ms 
    ****************************************************************************/
    void delay_xms(u16 nms)    {	 		  	  
    	u32 midtime;		   
    	SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
    	SysTick->VAL =0x00;           //清空计数器
    	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;          //开始倒数 
    	do	{
    		midtime=SysTick->CTRL;
    	}
    	while((midtime&0x01)&&!(midtime&(1<<16)));//等待时间到达 
    	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       //关闭计数器
    	SysTick->VAL =0X00;       //清空计数器 	    
    } 
    /****************************************************************************
    * 名称: void delay_ms(u16 nms)
    * 功能:延时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);
    } 
    

    lcd.h

    #ifndef __LCD_H
    #define __LCD_H		
    #include "delay.h"	 
    #include "stdlib.h" 
     
    //LCD驱动重要参数集
    extern  u16  lcd_id;         //LCD ID
    extern  u8   dir_flag;       //横屏还是竖屏控制:0,竖屏;1,横屏	
    extern  u16  lcd_width;      //LCD宽度
    extern  u16  lcd_height;     //LCD高度
    extern  u16	 write_gramcmd;	 //写gram指令
    extern	u16  setxcmd;		     //设置x坐标指令
    extern	u16  setycmd;		     //设置y坐标指令	 
    
    //LCD的画笔颜色和背景色  
    extern u16  BRUSH_COLOR;//默认红色
    extern u16  BACK_COLOR; //背景颜色 默认为白色
     
    //-----------------LCD背光端口定义---------------- 
    #define	LCD_BACK PDOut(3)//PFout(10)  //LCD背光    	PF10 	    
    
    //根据硬件电路图可以看靠我们使用NOR/SRAM的Bank1.sector4,地址位 HADDR[27,26]=11
    //A12作为数据命令区分线
    //因为我们使用的是16位的数据高度,所以要注意设置时STM32内部会右移一位对齐	    
    #define  CMD_BASE        ((u32)(0x6C000000 | 0x00000000))
    #define  DATA_BASE       ((u32)(0x6C000000 | 0x00002000))
    
    #define LCD_CMD       ( * (volatile u16 *) CMD_BASE )
    #define LCD_DATA      ( * (volatile u16 *) DATA_BASE)
    	 
    //扫描方向定义
    #define L2R_U2D  0 //从左到右 从上到下
    #define L2R_D2U  1 //从左到右 从下到上
    #define R2L_U2D  2 //从右到左 从上到下
    #define R2L_D2U  3 //从右到左 从下到上
    
    #define U2D_L2R  4 //从上到下 从左到右
    #define U2D_R2L  5 //从上到下 从右到左
    #define D2U_L2R  6 //从下到上 从左到右
    #define D2U_R2L  7 //从下到上 从右到左
    
    #define INIT_SCAN_DIR  R2L_U2D   //设置初始化扫描方向
    
    //颜色值定义
    #define WHITE        0xFFFF
    #define BLACK        0x0000	  
    #define BLUE         0x001F 
    #define GREEN        0x07E0
    #define BRED         0XF81F
    #define GRED 			   0XFFE0
    #define GBLUE			   0X07FF
    #define BROWN 			 0XBC40  
    #define BRRED 			 0XFC07  
    #define GRAY  			 0X8430  
    #define RED          0xF800
    #define MAGENTA      0xF81F
    #define CYAN         0x7FFF
    #define YELLOW       0xFFE0
    #define DARKBLUE      	 0X01CF	//深蓝
    #define LIGHTBLUE      	 0X7D7C	//浅蓝
    #define GRAYBLUE       	 0X5458 //灰蓝
    #define JBS        for(JBS=RED;JBS<=DARKBLUE;JBS++)
    
    void LCD_WriteReg(u16 LCD_Reg, u16 LCD_Value);
    u16 LCD_ReadReg(u16 LCD_Reg);
    void LCD_WriteRAM_Prepare(void);
    
    void LCD_Init(void);//初始化
    void LCD_DisplayOn(void);//开显示
    void LCD_DisplayOff(void);//关显示
    void LCD_Clear(u16 Color);//清屏
    void LCD_SetCursor(u16 Xpos, u16 Ypos);						//设置光标
    void LCD_DrawPoint(u16 x,u16 y);									//画点
    void LCD_Color_DrawPoint(u16 x,u16 y,u16 color);	//颜色画点
    u16  LCD_GetPoint(u16 x,u16 y); 								  //读点
    
    void LCD_AUTOScan_Dir(u8 dir);					 
    void LCD_Display_Dir(u8 dir);						 
    void LCD_Set_Window(u16 sx,u16 sy,u16 width,u16 height); 	
    
    void LCD_Draw_Circle(u16 x0,u16 y0,u8 r);	//画图
    void LCD_Draw_Line(u16 x1, u16 y1, u16 x2, u16 y2);//画线
    void LCD_Draw_Rectangle(u16 x1, u16 y1, u16 x2, u16 y2);		   	//画矩形
    void LCD_Fill_onecolor(u16 sx,u16 sy,u16 ex,u16 ey,u16 color);		//填充单个颜色
    void LCD_Draw_Picture(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color);		//填充指定颜色
    void LCD_DisplayChar(u16 x,u16 y,u8 word,u8 size);						      //显示一个字符
    void LCD_DisplayOTherChar(u16 x,u16 y,u8 word,u8 size);							//显示除ASCII之外的字符
    void LCD_DisplayNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode);				//显示 数字
    void LCD_DisplayNum_color(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode,u16 brushcolor,u16 backcolor); //显示自定义数字
    void LCD_DisplayString(u16 x,u16 y,u8 size,u8 *p);		           //显示一个12/16/24字体字符串
    void LCD_DisplayString_color(u16 x,u16 y,u8 size,u8 *p,u16 brushcolor,u16 backcolor); //显示一个12/16/24字体自定义颜色的字符串
    	  	   							
    void LCD_DisplayMyname(u16 x,u16 y);
    void LCD_DisplayTu1(u16 x,u16 y);
    void LCD_DisplayTu2(u16 x,u16 y);
    
    #endif  
    

    lcd.c

    #include "lcd.h"
    #include "cfont.h"    	 
    				 
    //初始化LCD的画笔颜色和背景色	   
    u16 BRUSH_COLOR=BLACK;	//画笔颜色
    u16 BACK_COLOR=WHITE;  //背景色
    
    //管理LCD驱动重要参数
      u16  lcd_id;          //LCD ID
      u16  lcd_width;       //LCD的宽度
      u16  lcd_height;      //LCD的高度
      u16 write_gramcmd=0X2C;
      u16 read_gramcmd = 0x2E;
      u16 setxcmd=0X2A;
      u16 setycmd=0X2B;
    	  
    /****************************************************************************
    * 名称: void LCD_WriteReg(u16 LCD_Reg, u16 LCD_Value)
    * 功能:LCD写寄存器
    * 入口参数:LCD_Reg: 寄存器地址
    *              LCD_RegValue: 要写入的数据
    ****************************************************************************/				   
    void LCD_WriteReg(u16 LCD_Reg, u16 LCD_Value)    {	
    	LCD_CMD = LCD_Reg;		 //写入要写的寄存器序号
    	LCD_DATA = LCD_Value;  //向寄存器写入的数据	    		 
    }
    /****************************************************************************
    * 名称: u16 LCD_ReadReg(u16 LCD_Reg)
    * 功能:LCD读寄存器
    * 入口参数:LCD Reg:寄存器地址
    * 返回参数:督导该寄存器序号里的值     
    ****************************************************************************/	
    u16 LCD_ReadReg(u16 LCD_Reg)    {										   
    	LCD_CMD=LCD_Reg;		//写入要读的寄存器序号
    	delay_us(5);		  
    	return LCD_DATA;		//返回读到的值
    }   
    //开始写GRAM
    void LCD_WriteRAM_Prepare(void)    {
     	LCD_CMD=write_gramcmd;	  
    }
    //lcd延时函数
    void lcdm_delay(u8 i)    {
    	while(i--);
    }
    
    //LCD开启显示
    void LCD_DisplayOn(void)    {					   
    		   LCD_CMD=0x29;
    }	
    
    //LCD关闭显示
    void LCD_DisplayOff(void)    {	
    		   LCD_CMD=0x28;
    }   
    /****************************************************************************
    *名称: void LCD_SetCursor(u16 Xaddr, u16 Yaddr)
    * 功能:设置光标位置
    * 入口参数:x:x坐标      y:y坐标    
    ****************************************************************************/
    void LCD_SetCursor(u16 Xaddr, u16 Yaddr)    {	     
    		LCD_CMD=setxcmd; 
    		LCD_DATA=(Xaddr>>8); 
    		LCD_DATA=(Xaddr&0XFF);	 
    		LCD_CMD=setycmd; 
    		LCD_DATA=(Yaddr>>8); 
    		LCD_DATA=(Yaddr&0XFF);
    } 
    /****************************************************************************
    * 名称: void LCD_AUTOScan_Dir(u8 dir)
    * 功能:设置LCD的自动扫描方向
    * 入口参数:dir:扫描方向  
    ****************************************************************************/  	   
    void LCD_AUTOScan_Dir(u8 dir)    {
    	u16 regval=0;
    	u16 dirreg=0; 
    
    	switch(dir)    {
    		case L2R_U2D://从左到右 从上到下 
    			regval|=(0<<7)|(0<<6)|(0<<5); break;
    		case L2R_D2U://从左到右 从下到上
    			regval|=(1<<7)|(0<<6)|(0<<5); break;
    		case R2L_U2D://从右到左 从上到下
    			regval|=(0<<7)|(1<<6)|(0<<5); break;
    		case R2L_D2U://从右到左 从下到上
    			regval|=(1<<7)|(1<<6)|(0<<5); break;	 
    		case U2D_L2R://从上到下 从左到右
    			regval|=(0<<7)|(0<<6)|(1<<5); break;
    		case U2D_R2L://从上到下 从右到左
    			regval|=(0<<7)|(1<<6)|(1<<5); break;
    		case D2U_L2R://从下到上 从左到右
    			regval|=(1<<7)|(0<<6)|(1<<5);break;
    		case D2U_R2L://从下到上 从右到左
    			regval|=(1<<7)|(1<<6)|(1<<5); break;	 
    	}
    
    	//设置扫描方法
    	dirreg=0X36;  
    	regval|=0X08;		
    	LCD_WriteReg(dirreg,regval);
    	
    	LCD_CMD=setxcmd; //x的最小值
    	LCD_DATA=0;
    	LCD_DATA=0;//x的最大值
    	LCD_DATA=(lcd_width-1)>>8;
    	LCD_DATA=(lcd_width-1)&0XFF;
    	LCD_CMD=setycmd; //y的最小值
    	LCD_DATA=0;
    	LCD_DATA=0;//y的最大值
    	LCD_DATA=(lcd_height-1)>>8;
    	LCD_DATA=(lcd_height-1)&0XFF;  
    }
    /****************************************************************************
    * 名称: void LCD_Display_Dir(u8 dir)
    * 功能:这只LCD显示方向
    * 入口参数:dir: 0,竖屏  1,横屏
    ****************************************************************************/
    void LCD_Display_Dir(u8 dir)    { 
    	switch (dir) {
    		case L2R_U2D:
    		case L2R_D2U:
    		case R2L_U2D:
    		case R2L_D2U:
    			//先左右后上下的是竖屏
    			lcd_width=240;
    			lcd_height=320;	
    			break;
    		default:
    			//先上下后左右的是横屏显示
    			lcd_width=320;
    			lcd_height=240;
    			break;
    	}
    	
    	LCD_AUTOScan_Dir(dir);	//设置扫描方向
    }	
    
    /****************************************************************************
    * 名称: u16 LCD_GetPoint(u16 x,u16 y)
    * 读取某点的颜色值
    * 入口参数:x:x坐标   y:y坐标
    * 返回参数:此点的颜色
    ****************************************************************************/
    u16 LCD_GetPoint(u16 x,u16 y)    {
     	vu16 r=0,g=0,b=0;
    
    	if(x>=lcd_width||y>=lcd_height)
    		return 0;	 //超过了范围 直接返回	   
    	LCD_SetCursor(x,y);	    
    	LCD_CMD = read_gramcmd;   //9341 发送读GRAM指令	 				 
    	if(LCD_DATA)
    		r=0;						
    	lcdm_delay(2);	  
     	r=LCD_DATA;  		  						 //实际坐标颜色
    	
    	lcdm_delay(2);	  
    	b=LCD_DATA; 
    	g=r&0XFF;		 //对于9341第一次读取的是RG的值 R在前 G在后 个占8位
    	g<<=8;
    
    	return (((r>>11)<<11)|((g>>10)<<5)|(b>>11)); //ILI9341需要公式转换一下}	
    
    /****************************************************************************
    * 名称: void LCD_DrawPoint(u16 x,u16 y)
    * 功能:画点(在该点写入画笔的颜色)
    * 入口参数:x:x坐标   y:y坐标
    * 返回参数:无
    * 说明 RUSH_COLOR:此点的颜色值
    ****************************************************************************/
    void LCD_DrawPoint(u16 x,u16 y)    {
    	LCD_SetCursor(x,y);		    //设置光标位置 
    	LCD_WriteRAM_Prepare();	  //开始写入GRAM
    	LCD_DATA=BRUSH_COLOR; 
    }
    /****************************************************************************
    * 名称: void LCD_Color_DrawPoint(u16 x,u16 y,u16 color)
    * 功能:在设置的坐标除画相应颜色(在该点写入自定义颜色)
    * 入口参数:x:x坐标  y:y坐标
                color 此点的颜色值
    *说明:color:写入此点的颜色值   UCGUI调用该函数
    ****************************************************************************/
    void LCD_Color_DrawPoint(u16 x,u16 y,u16 color)    {	       
    		LCD_CMD=setxcmd; 
    		LCD_DATA=(x>>8); 
    		LCD_DATA=(x&0XFF);	 
    		LCD_CMD=setycmd; 
    		LCD_DATA=(y>>8); 
    		LCD_DATA=(y&0XFF);
    		
    	  LCD_CMD=write_gramcmd; 
    	  LCD_DATA=color; 
    }	 
    /****************************************************************************
    * 名称: void LCD_Set_Window(u16 sx,u16 sy,u16 width,u16 height)
    * 功能:设置窗口,最后并设置画点坐标到窗口左上角(sx,sy)
    *入口参数:sx,sy:窗口起始坐标(左上角)     width,height:窗口宽度和高度
    *说明:窗口大小width*height.
    ****************************************************************************/
    void LCD_Set_Window(u16 sx,u16 sy,u16 width,u16 height)    {   
    	width=sx+width-1;
    	height=sy+height-1;
    	LCD_CMD=setxcmd; 
    	LCD_DATA=(sx>>8); 
    	LCD_DATA=(sx&0XFF);	 
    	LCD_DATA=(width>>8); 
    	LCD_DATA=(width&0XFF);  
    	LCD_CMD=setycmd; 
    	LCD_DATA=(sy>>8); 
    	LCD_DATA=(sy&0XFF); 
    	LCD_DATA=(height>>8); 
    	LCD_DATA=(height&0XFF); 
    } 
    
    /****************************************************************************
    * 名称: void LCD_Clear(u16 color)
    * 功能:清屏函数
    * 入口参数:color: 要清屏的填充色
    ****************************************************************************/
    void LCD_Clear(u16 color)    {
    	u32 i=0;      
    	u32 pointnum=0;
    	
    	pointnum=lcd_width*lcd_height; 	 //得到LCD总点数
    	LCD_SetCursor(0x00,0x00);	       //设置光标位置
    	LCD_WriteRAM_Prepare();     		 //开始写入GRAM	 	  
    	for(i=0;i<pointnum;i++)	{
    		LCD_DATA=color;	   
    	}
    } 
    /****************************************************************************
    * 名称: void LCD_Fill_onecolor(u16 sx,u16 sy,u16 ex,u16 ey,u16 color)
    *功能:在指定的区域内填充单个颜色
    * 入口参数:(sx,sy),(ex,ey):填充矩形对角坐标    color:要填充的颜色
    *说明:区域大小为:(ex-sx+1)*(ey-sy+1) 
    ****************************************************************************/
    void LCD_Fill_onecolor(u16 sx,u16 sy,u16 ex,u16 ey,u16 color)    {          
    	u16 i,j;
    	u16 nlen=0;
    
    		nlen=ex-sx+1;	 
    		for(i=sy;i<=ey;i++)    {
    		 	LCD_SetCursor(sx,i);      				  //设置光标位置 
    			LCD_WriteRAM_Prepare();     			  //开始写入GRAM	  
    			for(j=0;j<nlen;j++)LCD_DATA=color;	//设置光标位置 	    
    		}
    } 
    /****************************************************************************
    * 名称: void LCD_Draw_Picture(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color)
    * 功能:在指定区域内画入图片
    * 入口参数:(sx,sy),(ex,ey):填充矩形对角坐标     color:要填充的图片像素颜色数组
    *说明:区域大小为:(ex-sx+1)*(ey-sy+1)
    ****************************************************************************/
    void LCD_Draw_Picture(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color)    {  
    	u16 height,width;
    	u16 i,j;
    	width=ex-sx+1; 			    //得到图片的宽度
    	height=ey-sy+1;			    //得到图片的高度
     	for(i=0;i<height;i++)    	{
     		LCD_SetCursor(sx,sy+i);   	//设置光标位置
    		LCD_WriteRAM_Prepare();     //开始写入GRAM
    		for(j=0;j<width;j++)LCD_DATA=color[i*height+j];//写入颜色值
    	}	  
    }  
    /****************************************************************************
    * 名称: void LCD_Draw_Line(u16 x1, u16 y1, u16 x2, u16 y2)
    * 功能:画线
    * 入口参数:x1,y1:起点坐标    x2,y2:终点坐标
    * 说明:有三种情况的画线,水平线、垂直线与斜线(画线、划矩形与画圆参考网上代码)
    ************************2****************************************************/  
    void LCD_Draw_Line(u16 x1, u16 y1, u16 x2, u16 y2)    {
    	u16 i; 
    	int xm1=0,ym2=0,model_x,model_y,model,  mcx,mcy,mRow,mCol;  
    
    	model_x=x2-x1;                  //计算直线的模 画线坐标增量
    	model_y=y2-y1; 
    	mRow=x1; 
    	mCol=y1; 
    	if(model_x>0)mcx=1;       
    	else if(model_x==0)mcx=0;      //垂直线
    	else {mcx=-1;model_x=-model_x;} 
    	if(model_y>0)mcy=1; 
    	else if(model_y==0)mcy=0;      //水平线
    	else{mcy=-1;model_y=-model_y;} 
    	if( model_x>model_y)model=model_x;  
    	else model=model_y; 
    	for(i=0;i<=model+1;i++ )       //画线输出
    	{  
    		LCD_DrawPoint(mRow,mCol);     
    		xm1+=model_x ; 
    		ym2+=model_y ; 
    		if(xm1>model)     { 
    			xm1-=model; 
    			mRow+=mcx; 
    		} 
    		if(ym2>model)     { 
    			ym2-=model; 
    			mCol+=mcy; 
    		} 
    	}  
    }
    /****************************************************************************
    * 名称: void LCD_Draw_Rectangle(u16 x1, u16 y1, u16 x2, u16 y2)
    * 功能:画矩形  
    * 入口参数:(x1,y1),(x2,y2):矩形的对角坐标
    ****************************************************************************/
    void LCD_Draw_Rectangle(u16 x1, u16 y1, u16 x2, u16 y2)    {
    	LCD_Draw_Line(x1,y1,x2,y1);
    	LCD_Draw_Line(x1,y1,x1,y2);
    	LCD_Draw_Line(x1,y2,x2,y2);
    	LCD_Draw_Line(x2,y1,x2,y2);
    }
    /****************************************************************************
    * 名称: void LCD_Draw_Circle(u16 x0,u16 y0,u8 r)
    *功能:字指定位置画一个指定大小的圆
    * 入口参数:(x,y):中心点      r :半径
    ****************************************************************************/
    void LCD_Draw_Circle(u16 x0,u16 y0,u8 r)    {
    	int a,b;
    	int di;
    	a=0;b=r;	  
    	di=3-(r<<1);             //判断下个点位置的标志
    	while(a<=b)	{
    		LCD_DrawPoint(x0+a,y0-b);             
     		LCD_DrawPoint(x0+b,y0-a);                    
    		LCD_DrawPoint(x0+b,y0+a);                       
    		LCD_DrawPoint(x0+a,y0+b);             
    		LCD_DrawPoint(x0-a,y0+b);             
     		LCD_DrawPoint(x0-b,y0+a);             
    		LCD_DrawPoint(x0-a,y0-b);                      
      	LCD_DrawPoint(x0-b,y0-a);               	         
    		a++;	
    		if(di<0)di +=4*a+6;	  //使用Bresenham算法画圆
    		else	{
    			di+=10+4*(a-b);   
    			b--;
    		} 						    
    	}
    } 
    
    /****************************************************************************
    * 名称: void LCD_DisplayChar(u16 x,u16 y,u8 num,u8 size)
    * 功能:在指定位置显示一个字符
    * 入口参数:x,y:起始坐标
                word:要显示的字符:abcdefg1234567890...
                size:字体大小 12/16/24
    *说明:取字模参考网上取字模方式,改字模取模方向为先从上到下,再从左到右
    ****************************************************************************/
    void LCD_DisplayChar(u16 x,u16 y,u8 word,u8 size)    {  							  
      u8  bytenum,bytedata, a,b;
    	u16 ymid=y;   			     
    	 
    	if(size==12) bytenum=12;        // 判断各个字体子啊字库数组中占的字节数
    	else if(size==16) bytenum=16;
    	else if(size==24) bytenum=36;
    	else return;
    	
    	word=word-' ';  //得到偏移后的值 因为空格之前的字符没在font.h中的数组里面
    	    for(b=0;b<bytenum;b++)    {   
    					if(size==12)bytedata=char_1206[word][b]; 	 	  //调用1206字体
    					else if(size==16)bytedata=char_1608[word][b];	//调用1608字体
    					else if(size==24)bytedata=char_2412[word][b];	//调用2412字体
    					else return;								                  //没有的字符数组 没字符字库
    					for(a=0;a<8;a++)	{			    
    						if(bytedata&0x80)LCD_Color_DrawPoint(x,y,BRUSH_COLOR);
    						else LCD_Color_DrawPoint(x,y,BACK_COLOR);
    						bytedata<<=1;
    						y++;
    						if(y>=lcd_height)return;		//超区域 退出函数
    						if((y-ymid)==size)	{
    							y=ymid;
    							x++;
    							if(x>=lcd_width)return;	  //超区域 退出函数
    							break;
    						}
    		      }   	 
    	    }       	 	  
    }   
    
    /****************************************************************************
    * 名称: void LCD_DisplayOtherChar(u16 x,u16 y,u8 num,u8 size)
    * 功能:在指定位置显示一个除ASCII之外的字符
    * 入口参数:x,y:起始坐标     word:要显示的字符    0:摄氏度标志   size:字体大小 12/16/24
    * 说明:取字模参考网上 该字模取模方向为先从上到下 再从左到右
    ****************************************************************************/
    void LCD_DisplayOTherChar(u16 x,u16 y,u8 word,u8 size)    {  							  
      u8  bytenum,bytedata, a,b;
    	u16 ymid=y;   			     
    	 
    	if(size==12) bytenum=24;        // 判断各个字体子啊字库数组中占的字节数
    	else if(size==16) bytenum=32;
    	else if(size==24) bytenum=72;
    	else return;
    
    	for(b=0;b<bytenum;b++)    	{   
    			if(size==12)bytedata=otherChar_1212[word][b]; 	 	  //调用1212字体
    			else if(size==16)bytedata=otherChar_1616[word][b];	//调用1616字体
    			else if(size==24)bytedata=otherChar_2424[word][b];	//调用2424字体
    			else return;								                  		  //没有的字符数组,没字符字库
    		
    			for(a=0;a<8;a++)    {			    
    				if(bytedata&0x80)LCD_Color_DrawPoint(x,y,BRUSH_COLOR);
    				else LCD_Color_DrawPoint(x,y,BACK_COLOR);
    				bytedata<<=1;
    				y++;
    				if(y>=lcd_height)return;		//超区域 退出函数
    				if((y-ymid)==size)    {
    					y=ymid;
    					x++;
    					if(x>=lcd_width)return;	  //超区域 退出函数
    					break;
    				}
    			}   	 
    	}       	 	  
    }   
    //m^n函数
    //返回值:m^n次方
    u32 LCD_Pow(u8 m,u8 n)    {
    	u32 mid=1;	 
    	while(n--)mid*=m;    
    	return mid;
    }
    /****************************************************************************
    * 名称: : void LCD_DisplayNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode)
    * 功能: 在指定位置显示一串数字
    * 入口参数:x,y:起始坐标
                num:数值(0~999999999);	 
                len:长度(即要显示的位数)
                size:字体大小
                mode: 0:高位为0 不显示
                      1:高位为0显示0
    ****************************************************************************/
    void LCD_DisplayNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode)    {  
    	u8 t,numtemp;
    	u8 end0=0;						   
    	for(t=0;t<len;t++)    	{
    		numtemp=(num/LCD_Pow(10,len-t-1))%10;
    		if(end0==0&&t<(len-1))	{
    			if(numtemp==0)    {
    				if(mode)LCD_DisplayChar(x+(size/2)*t,y,'0',size);  
    				else LCD_DisplayChar(x+(size/2)*t,y,' ',size);  
     				continue;
    			}else end0=1; 	 
    		}
    	 	LCD_DisplayChar(x+(size/2)*t,y,numtemp+'0',size); 
    	}
    } 
    /****************************************************************************
    * 名称: void LCD_DisplayNum_color(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode)
    * 功能:在指定位置显示一串自定义颜色的数字
    * 入口参数: x,y:起始坐标
                num:数值(0~999999999);	 
                len:长度(即要显示的位数)
                size:字体大小
                mode: 0:高位为0 不显示     1:高位为0显示0
                brushcolor:自定义画笔颜色
                backcolor:自定义背景颜色
    ****************************************************************************/
    void LCD_DisplayNum_color(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode,u16 brushcolor,u16 backcolor)    {
     u16 bh_color,bk_color;
    	
     	bh_color=BRUSH_COLOR;  //暂存画笔颜色
    	bk_color=BACK_COLOR;   //暂存背景颜色
    	
    	BRUSH_COLOR=brushcolor;
    	BACK_COLOR=backcolor;
    	
    	LCD_DisplayNum(x,y,num,len,size,mode);
    	
    	BRUSH_COLOR=bh_color;   //不改变系统颜色
    	BACK_COLOR=bk_color;
    }
    /****************************************************************************
    * 名称: void LCD_DisplayString(u16 x,u16 y,u8 size,u8 *p)
    * 功能:显示字符串
    * 入口参数:x,y:起始坐标
    *           size:字体大小    *p:字符串起始地址
    ****************************************************************************/	  
    void LCD_DisplayString(u16 x,u16 y,u8 size,u8 *p)    {
    	
        while((*p<='~')&&(*p>=' ')) //判断是不是非法字符!  {       
            LCD_DisplayChar(x,y,*p,size);
            x+=size/2;
    			  if(x>=lcd_width) break;
            p++;
        }  
    }
    /****************************************************************************
    *名称: : void LCD_DisplayString(u16 x,u16 y,u8 size,u8 *p)
    * 功能: 显示自定义字符串
    * 入口参数:x,y:起始坐标
    *           width,height:区域大小
    *           size:字体大小
    *           *p:字符串起始地址	
    *           brushcolor:自定义画笔颜色
    *           backcolor:自定义背景颜色
    ****************************************************************************/	  
    void LCD_DisplayString_color(u16 x,u16 y,u8 size,u8 *p,u16 brushcolor,u16 backcolor)    {
       u16 bh_color,bk_color;
    	
     	bh_color=BRUSH_COLOR;  //暂存画笔颜色
    	bk_color=BACK_COLOR;   //暂存背景颜色
    	
    	BRUSH_COLOR=brushcolor;
    	BACK_COLOR=backcolor;
    	
    	LCD_DisplayString(x,y,size,p);
    	
    	BRUSH_COLOR=bh_color;   //不改变系统颜色
    	BACK_COLOR=bk_color;
    }
    
    //配置FSMC可变静态存储控制器
    void LCD_FSMC_Config()    {
    	GPIO_InitTypeDef  GPIO_InitStructure;
    	FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
      FSMC_NORSRAMTimingInitTypeDef  readWriteTiming; 
    	FSMC_NORSRAMTimingInitTypeDef  writeTiming;
    	
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOF|RCC_AHB1Periph_GPIOG, ENABLE);//使能PD PE PF PG时钟
      RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE);//使能FSMC时钟
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;        //PF10 推挽输出 控制背光
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;     //普通输出模式
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;    //推挽输出
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //100MHz
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;      //上拉
      GPIO_Init(GPIOD, &GPIO_InitStructure);            //初始化 //
    	
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15; 
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;      //复用输出
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;    //推挽输出
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;      //上拉
      GPIO_Init(GPIOD, &GPIO_InitStructure);            //初始化
    	
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | 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_Mode = GPIO_Mode_AF;      //复用输出
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;    //推挽输出
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;      //上拉­
      GPIO_Init(GPIOE, &GPIO_InitStructure);            //初始化 
    
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;         //PG2,FSMC_A12
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;      //¸´ÓÃÊä³ö
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;    //ÍÆÍìÊä³ö
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;      //ÉÏÀ­
      GPIO_Init(GPIOG, &GPIO_InitStructure);            //³õʼ»¯  
    
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;        //PG12
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;      //复用输出
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;    //推挽输出
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;      //上拉­­
      GPIO_Init(GPIOG, &GPIO_InitStructure);            //初始化
    
      GPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_FSMC);//PD0,AF12
      GPIO_PinAFConfig(GPIOD,GPIO_PinSource1,GPIO_AF_FSMC);//PD1,AF12
      GPIO_PinAFConfig(GPIOD,GPIO_PinSource4,GPIO_AF_FSMC);
      GPIO_PinAFConfig(GPIOD,GPIO_PinSource5,GPIO_AF_FSMC); 
      GPIO_PinAFConfig(GPIOD,GPIO_PinSource8,GPIO_AF_FSMC); 
      GPIO_PinAFConfig(GPIOD,GPIO_PinSource9,GPIO_AF_FSMC);
      GPIO_PinAFConfig(GPIOD,GPIO_PinSource10,GPIO_AF_FSMC);
      GPIO_PinAFConfig(GPIOD,GPIO_PinSource14,GPIO_AF_FSMC);
      GPIO_PinAFConfig(GPIOD,GPIO_PinSource15,GPIO_AF_FSMC);//PD15,AF12
     
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource7,GPIO_AF_FSMC); //PE7,AF12
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource8,GPIO_AF_FSMC);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_FSMC);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource10,GPIO_AF_FSMC);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_FSMC);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource12,GPIO_AF_FSMC);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_FSMC);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_FSMC);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource15,GPIO_AF_FSMC);//PE15,AF12
     
      GPIO_PinAFConfig(GPIOG,GPIO_PinSource2,GPIO_AF_FSMC);//PF12,AF12
      GPIO_PinAFConfig(GPIOG,GPIO_PinSource12,GPIO_AF_FSMC);
    
      readWriteTiming.FSMC_AddressSetupTime = 0XF;	 //地址建立时间(ADDSET)为16个HCLK 1/168M=6ns*16=96ns	> 90
      readWriteTiming.FSMC_AddressHoldTime = 0x00;	 //地址保持时间(ADDHLD)模式A未用到
      readWriteTiming.FSMC_DataSetupTime = 60;			 //数据存储时间为60个HCLK	=6*60=360ns > 255
      readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
      readWriteTiming.FSMC_CLKDivision = 0x00;
      readWriteTiming.FSMC_DataLatency = 0x00;
      readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A;	 //模式A 
        
    	writeTiming.FSMC_AddressSetupTime = 3;	   //地址建立时间(ADDSET)为3个HCLK =18ns > 15
      writeTiming.FSMC_AddressHoldTime = 0x00;	 //地址保持时间(ADDHLD) 模式A不使用
      writeTiming.FSMC_DataSetupTime = 2;		     //数据保存时间为6ns*3个HCLK=18ns > 15
      writeTiming.FSMC_BusTurnAroundDuration = 0x00;
      writeTiming.FSMC_CLKDivision = 0x00;
      writeTiming.FSMC_DataLatency = 0x00;
      writeTiming.FSMC_AccessMode = FSMC_AccessMode_A;	 //模式A 
    
      FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;//   使用E4,也就对应BTCR[6],[7]
      FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; // 不复用数据地址
      FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_SRAM;// FSMC_MemoryType_SRAM;  //SRAM   
      FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;//存储器数据宽度为16bit   
      FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;// FSMC_BurstAccessMode_Disable; 
      FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
    	FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable; 
      FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;   
      FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;  
      FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;	//存储器写使能
      FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;   
      FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable; // 读写使用不同的时序
      FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; 
      FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming; //读写时序
      FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &writeTiming;  //写时序
      FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);  //初始化FSMC配置
      FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);  // 使能BANK1 
    				 
      delay_ms(50); // delay 50 ms 
    }
    //初始化lcd
    void LCD_Init(void)    { 			
    		LCD_FSMC_Config();
    		
     		//尝试9341 ID的读取		
    		LCD_CMD=0XD3;				   
    		lcd_id=LCD_DATA;	//dummy read 	
     		lcd_id=LCD_DATA; 	//读到0X00
      	        lcd_id=LCD_DATA;   	//读取93								   
     		lcd_id<<=8;
    		lcd_id|=LCD_DATA;  	//读取41 
    	
    		LCD_CMD=0xCF;  
    		LCD_DATA=0x00;
    		LCD_DATA=0xC1; 
    		LCD_DATA=0X30; 
    		LCD_CMD=0xED;  
    		LCD_DATA=0x64; 
    		LCD_DATA=0x03; 
    		LCD_DATA=0X12; 
    		LCD_DATA=0X81; 
    		LCD_CMD=0xE8;  
    		LCD_DATA=0x85; 
    		LCD_DATA=0x10; 
    		LCD_DATA=0x7A; 
    		LCD_CMD=0xCB;  
    		LCD_DATA=0x39; 
    		LCD_DATA=0x2C; 
    		LCD_DATA=0x00; 
    		LCD_DATA=0x34; 
    		LCD_DATA=0x02; 
    		LCD_CMD=0xF7;  
    		LCD_DATA=0x20; 
    		LCD_CMD=0xEA;  
    		LCD_DATA=0x00; 
    		LCD_DATA=0x00; 
    		LCD_CMD=0xC0;    //Power control 
    		LCD_DATA=0x1B;   //VRH[5:0] 
    		LCD_CMD=0xC1;    //Power control 
    		LCD_DATA=0x01;   //SAP[2:0];BT[3:0] 
    		LCD_CMD=0xC5;    //VCM control 
    		LCD_DATA=0x30; 	 //3F
    		LCD_DATA=0x30; 	 //3C
    		LCD_CMD=0xC7;    //VCM control2 
    		LCD_DATA=0XB7; 
    		LCD_CMD=0x36;    // Memory Access Control 
    		LCD_DATA=0x48; 
    		LCD_CMD=0x3A;   
    		LCD_DATA=0x55; 
    		LCD_CMD=0xB1;   
    		LCD_DATA=0x00;   
    		LCD_DATA=0x1A; 
    		LCD_CMD=0xB6;    // Display Function Control 
    		LCD_DATA=0x0A; 
    		LCD_DATA=0xA2; 
    		LCD_CMD=0xF2;    // 3Gamma Function Disable 
    		LCD_DATA=0x00; 
    		LCD_CMD=0x26;    //Gamma curve selected 
    		LCD_DATA=0x01; 
    		LCD_CMD=0xE0;    //Set Gamma 
    		LCD_DATA=0x0F; 
    		LCD_DATA=0x2A; 
    		LCD_DATA=0x28; 
    		LCD_DATA=0x08; 
    		LCD_DATA=0x0E; 
    		LCD_DATA=0x08; 
    		LCD_DATA=0x54; 
    		LCD_DATA=0XA9; 
    		LCD_DATA=0x43; 
    		LCD_DATA=0x0A; 
    		LCD_DATA=0x0F; 
    		LCD_DATA=0x00; 
    		LCD_DATA=0x00; 
    		LCD_DATA=0x00; 
    		LCD_DATA=0x00; 		 
    		LCD_CMD=0XE1;    //Set Gamma 
    		LCD_DATA=0x00; 
    		LCD_DATA=0x15; 
    		LCD_DATA=0x17; 
    		LCD_DATA=0x07; 
    		LCD_DATA=0x11; 
    		LCD_DATA=0x06; 
    		LCD_DATA=0x2B; 
    		LCD_DATA=0x56; 
    		LCD_DATA=0x3C; 
    		LCD_DATA=0x05; 
    		LCD_DATA=0x10; 
    		LCD_DATA=0x0F; 
    		LCD_DATA=0x3F; 
    		LCD_DATA=0x3F; 
    		LCD_DATA=0x0F; 
    		LCD_CMD=0x2B; 
    		LCD_DATA=0x00;
    		LCD_DATA=0x00;
    		LCD_DATA=0x01;
    		LCD_DATA=0x3f;
    		LCD_CMD=0x2A; 
    		LCD_DATA=0x00;
    		LCD_DATA=0x00;
    		LCD_DATA=0x00;
    		LCD_DATA=0xef;	 
    		LCD_CMD=0x11; //Exit Sleep
    		delay_ms(120);
    		LCD_CMD=0x29; //display on	
    		
    		LCD_Display_Dir(U2D_R2L);		 //初始化为 横屏
    		LCD_BACK=1;			   //点亮背光
    		LCD_Clear(WHITE);
    }
    
    void LCD_DisplayMyname(u16 x,u16 y)    {  							  
      u8  bytenum,bytedata, a,b;
    	u16 ymid=y;   			     
    	 
    	bytenum = sizeof(gao);//
    	
    	for(b=0;b<bytenum;b++)    	{   
    		bytedata=gao[b]; 	 	  //调用1206字体
    													                  //没有的字符数组 没字符字库
    		for(a=0;a<8;a++)	{			    
    			if(bytedata&0x80)LCD_Color_DrawPoint(x,y,RED);
    			else LCD_Color_DrawPoint(x,y,YELLOW);
    			bytedata<<=1;
    			y++;
    			if(y>=lcd_height)return;		//超区域 退出函数
    			if((y-ymid)==32)	{
    				y=ymid;
    				x++;
    				if(x>=lcd_width)return;	  //超区域 退出函数
    				break;
    			}
    		}   	 
    	}
    }   
    
    void LCD_DisplayTu1(u16 x,u16 y)    {
    	u8  bytenum,bytedata, a,b;
    	u16 ymid=y;   			     
    	 
    	bytenum = sizeof(biao1);//
    	
    	for(b=0;b<bytenum;b++)    	{   
    		bytedata=biao1[b]; 	 	  //调用1206字体
    													                  //没有的字符数组 没字符字库
    		for(a=0;a<8;a++)	{			    
    			if(bytedata&0x80)LCD_Color_DrawPoint(x,y,WHITE);
    			else LCD_Color_DrawPoint(x,y,BLUE);
    			bytedata<<=1;
    			y++;
    			if(y>=lcd_height)return;		//超区域 退出函数
    			if((y-ymid)==32)	{
    				y=ymid;
    				x++;
    				if(x>=lcd_width)return;	  //超区域 退出函数
    				break;
    			}
    		}   	 
    	}
    }
    
    void LCD_DisplayTu2(u16 x,u16 y)    {
    	u8  bytenum,bytedata, a,b;
    	u16 ymid=y;   			     
    	 
    	bytenum = sizeof(biao2);//
    	
    	for(b=0;b<bytenum;b++)    	{   
    		bytedata=biao2[b]; 	 	  //调用1206字体
    													                  //没有的字符数组 没字符字库
    		for(a=0;a<8;a++)	{			    
    			if(bytedata&0x80)LCD_Color_DrawPoint(x,y,WHITE);
    			else LCD_Color_DrawPoint(x,y,BLUE);
    			bytedata<<=1;
    			y++;
    			if(y>=lcd_height)return;		//超区域 退出函数
    			if((y-ymid)==32)	{
    				y=ymid;
    				x++;
    				if(x>=lcd_width)return;	  //超区域 退出函数
    				break;
    			}
    		}   	 
    	}	
    }
    

    cfont.h

    #ifndef __CFONT_H
    #define __CFONT_H 
    //字库均来源于网络工具生成  此处略
    //摄氏度符号
    const unsigned char otherChar_1212[1][24] = {{0x00,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0xC0,0x11,0x80,0x00,0x00}};
    
    const unsigned char otherChar_1616[1][32] = {{0x00,0x00,0x30,0x00,0x48,0x00,0x30,0x00,0x00,0x00,0x03,0xF0,0x0E,0x18,0x08,0x0C,0x10,0x04,0x10,0x04,0x10,0x04,0x10,0x04,0x08,0x0C,0x0C,0x38,0x00,0x00,0x00,0x00}};
    

    ds18b20.h

    #ifndef S3C_DS_H
    #define S3C_DS_H
    
    extern void DS18B20_Init(void);
    extern void get_temperature(char *buf);
    
    #endif
    

    ds18b20.c

    #include "stm32f4xx.h"
    #include "ds18b20.h"
    #include "delay.h"
    
    extern void gpio_out_state(int);
    extern int gpio_input_state(void);
    
    int  DS1820_Reset(void);                //DS1820 复位 
    void DS1820_WriteData(char wData);    	//写数据到 DS1820 
    
    /********************************************************** 
     *DS1820 复位及存在检测(通过存在脉冲可以判断 DS1820 是否损坏) 
     *函数名称:DS1820_Reset() 
     *说明:函数返回一个位标量(0 或 1)flag=0 存在,反之 flag=1 不存在 
     **********************************************************/ 
    int DS1820_Reset(void)     { 
    	int flag;         
    
    	gpio_out_state(0);
    	//延时 480 微秒,产生复位脉冲 
    	delay_us(480);
    	gpio_out_state(1);
    	//延时 80 微秒对总线采样 
    	delay_us(80);
    	flag = gpio_input_state();   
    	//对数据脚采样 
    	delay_us(400);    //延时 400 微秒等待总线恢复 
    
    	return flag;                //根据 flag 的值可知 DS1820 是否存在或损坏  ,可加声音告警提示 DS1820 故障 
    } 
    
    /********************************************************** 
     *写数据到 DS1820 
     *函数名称:DS1820_WriteData() 
     **********************************************************/ 
    void DS1820_WriteData(char wData)     { 
    	char i; 
    
    	for(i = 8; i > 0; i--)    {
    		gpio_out_state(0);                  //拉低总线,产生写信号 
    		delay_us(4);            		//延时 4us 
    		gpio_out_state(wData & 0x01); 	//发送 1 位 
    		delay_us(60);          		//延时 60us,写时序至少要 60us 
    		gpio_out_state(1);                  //释放总线,等待总线恢复 
    		wData >>= 1;                    //准备下一位数据的传送 
    	} 
    } 
    
    /********************************************************** 
     *DS18B20 初始化 
     *函数名称:DS1820_WriteData() 
     *说明:本初始化程序可以不要,因为 18B20 在出厂时就被配置为 12 位精度了 
     **********************************************************/ 
    void DS18B20_Init(void)  { 
    	DS1820_Reset(); 
    	DS1820_WriteData(0xCC);    //  跳过 ROM 
    	DS1820_WriteData(0x4E);    //  写暂存器 
    	DS1820_WriteData(0x20);    //  往暂存器的第三字节中写上限值 
    	DS1820_WriteData(0x00);    //  往暂存器的第四字节中写下限值 
    	DS1820_WriteData(0x7F);    //  将配置寄存器配置为 12 位精度 
    
    	DS1820_Reset(); 
    } 
    
    /********************************************************** 
     *从 DS1820 中读出数据 
     *函数名称:DS1820_ReadData() 
     **********************************************************/ 
    char DS1820_ReadData(void)     { 
    	char i,TmepData = 0; 
    
    	for(i = 8; i > 0; i--)    {
    		TmepData >>= 1; 
    		gpio_out_state(0);          //拉低总线,产生读信号 
    		delay_us(4);              	//延时 4us 
    		gpio_out_state(1);          //释放总线,准备读数据 
    		delay_us(8);              	//延时 8 微秒读数据 
    		if(gpio_input_state())
    			TmepData |= 0x80; 
    		delay_us(60);            		//延时 60us 
    		gpio_out_state(1);                  //拉高总线,准备下一位数据的读取. 
    	} 
    	return TmepData;			//返回读到的数据 
    } 
    
    /********************************************************** 
     *转换子程序 
     **********************************************************/ 
    void tem_to_string(char *buf, char temperature[])    { 
    	unsigned char temp_data,temp_data_2; 
    	unsigned short TempDec; 		//用来存放 4 位小数 
    
    	temp_data = temperature[1]; 
    	temp_data &= 0xf8;    			//取高 4 位 
    
    	if(temp_data == 0xf8)    { 			//判断是正温度还是负温度读数
    						//负温度读数求补,取反加 1,判断低 8 位是否有进位 
    		if(temperature[0]==0)    { 		//有进位,高 8 位取反加 1 
    			temperature[0]=~temperature[0]+1; 
    			temperature[1]=~temperature[1]+1; 
    		}else    { 				//没进位,高 8 位不加 1 
    			temperature[0]=~temperature[0]+1; 
    			temperature[1]=~temperature[1]; 
    		} 
    	} 
    	//温度格式  temperature[1]:[xxxxAAAA] AAAA 温度的高4位
    	//温度格式  temperature[0]:[BBBBCCCC] BBBB 温度的低4位 CCCC小数(乘以0.0625得到的是温度)
    	temp_data = temperature[1]<<4;      						//取高字节低 4 位(温度读数高 4 位),注意此时是 12 位精度 
    	temp_data_2 = temperature[0]>>4; 						//取低字节高 4 位(温度读数低 4 位),注意此时是 12 位精度 
    	temp_data = temp_data | temp_data_2; 					//组合成完整数据 
    	
    	buf[0] = temp_data / 100 + 0x30;      					//取百位转换为 ASCII 码 
    	buf[1] = (temp_data % 100) / 10 + 0x30;    			//取十位转换为 ASCII 码 
    	buf[2] = (temp_data % 100 ) % 10 + 0x30;    		//取个位转换为 ASCII 码 
    	buf[3] = '.';
    #if 0
    	1111	= 15;
    	2 ^ 3 + 2 ^ 2 + 2 ^ 1 + 2 ^ 0 = 15 
    	1111	= (2 ^ 3 + 2 ^ 2 + 2 ^ 1 + 2 ^ 0) * 0.0625	= 15 * 0.0625
    	
    #endif
    	temperature[0] &= 0x0f;                        	//取小数位转换为 ASCII 码 
    	TempDec = temperature[0] * 625;                	//625=0.0625*10000,表示小数部分,扩大 1 万倍  ,方便显示 
    	buf[4] = TempDec / 1000 + 0x30;                	//取小数十分位转换为 ASCII 码 
    	buf[5] = (TempDec % 1000) / 100 + 0x30;      		//取小数百分位转换为 ASCII 码 
    	buf[6] = ((TempDec % 1000) % 100) / 10 + 0x30;	//取小数千分位转换为 ASCII 码 
    	buf[7] = ((TempDec % 1000) % 100) % 10 + 0x30;	//取小数万分位转换为 ASCII 码 
    	buf[8] = '';
    }
    
    void get_temperature(char *buf)     { 
    	int i; 
    	char temperature[2]; //存放温度数据 
    
    	DS1820_Reset();                  //复位 
    	DS1820_WriteData(0xcc); //跳过 ROM 命令 
    	DS1820_WriteData(0x44); //温度转换命令 
    	DS1820_Reset();         //复位 
    	DS1820_WriteData(0xcc); //跳过 ROM 命令 
    	DS1820_WriteData(0xbe); //读 DS1820 温度暂存器命令 
    	for (i=0;i<2;i++){ 
    		temperature[i] = DS1820_ReadData();    //采集温度 
    	} 
    	DS1820_Reset();              //复位,结束读数据 
    	tem_to_string(buf, temperature);
    	delay_us(50);
    } 
    

    dht11.h

    #ifndef __DHT_H
    #define __DHT_H
    
    #include "stm32f4xx_conf.h"
    
    extern void dht_init(void);
    extern void dht_get_data(char *buf);
    
    #endif
    

    dht11.c

    #include "dht11.h"
    #include "delay.h"
    #include "bitband.h"
    
    void dht_init(void)    {
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    }
    
    void dht_gpio_out(void)    {
    	GPIO_InitTypeDef Gpio_Value;
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    	
    	Gpio_Value.GPIO_Mode = GPIO_Mode_OUT;
    	Gpio_Value.GPIO_OType = GPIO_OType_PP;
    	Gpio_Value.GPIO_Pin = GPIO_Pin_4;
    	Gpio_Value.GPIO_PuPd = GPIO_PuPd_NOPULL;
    	Gpio_Value.GPIO_Speed = GPIO_Fast_Speed;
    	
    	GPIO_Init(GPIOA, &Gpio_Value);	
    }
    
    void dht_gpio_in(void)    {
    	GPIO_InitTypeDef Gpio_Value;
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    	
    	Gpio_Value.GPIO_Mode = GPIO_Mode_IN;
    	Gpio_Value.GPIO_Pin = GPIO_Pin_4;
    	Gpio_Value.GPIO_PuPd = GPIO_PuPd_NOPULL;
    	Gpio_Value.GPIO_Speed = GPIO_Fast_Speed;
    	
    	GPIO_Init(GPIOA, &Gpio_Value);	
    }
    
    void dht_output_state(int state)    {
    	dht_gpio_out();
    	if(state)
    		PAOut(4) = 1;
    	else
    		PAOut(4) = 0;
    }
    
    int dht_input_state(void)    {
    	dht_gpio_in();
    	return PAIn(4);
    }
    
    void dht_get_data(char *buf)    {
    	char i;
    	char tmp = 0;
    	dht_output_state(0);
    	delay_ms(20);
    	dht_output_state(1);
    	
    	while(dht_input_state());
    	while(!dht_input_state());
    	
    	for(i = 0; i < 40; i++)    	{
    		while(dht_input_state());
    		while(!dht_input_state());
    		delay_us(40);
    		tmp <<= 1;
    		if(dht_input_state())
    			tmp |= 1;
    		if((i + 1) % 8 == 0)// 7 15 23 31	{
    			buf[i / 8] = tmp;
    			tmp = 0;
    		}
    	}
    	dht_output_state(1);
    }
    
    http://www.cnblogs.com/OceanF/
  • 相关阅读:
    ORM框架
    优酷项目1
    新年第一天
    前端第十天
    前端第九天
    前端第八天
    前端第七天
    前端第六天
    前端第五天
    月亮与六便士
  • 原文地址:https://www.cnblogs.com/OceanF/p/9150998.html
Copyright © 2011-2022 走看看