软件
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;i0)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=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=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=' ')) //判断是不是非法字符! {
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=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=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=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] = '\0';
}
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);
}