DS18B20温度传感器
这个温度传感器为单总线通信,测量温度范围为-55~+125℃ ,精度为±0.5℃。现场温度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性。它能直接读出被测温度,并且可根据实际要求通过简单的编程实现 9~l2 位的数字值读数方式。
内部有64位ROM用来储存家族编码,序列号,以及校验码。每个产品都不一样,这样可以在一个总线上面挂载多个。单总线器件有严格的信号时序,DS18B20一共有6种信号。
信号时序:
-
复位脉冲和应答脉冲
主机输出低电平,保持低电平时间至少480us,产生复位脉冲,接着释放总线(用4.7K的上拉电阻将总线拉高),演示15-60us,接着 进入接收模式,18B20的应答信号是拉低总线60~240us。 -
写时序0/1
写1时拉低总线延时2us,在拉高电平持续60us。写0时拉低电平60us再拉高电平2us。 -
读时序0/1
拉低总线延时2us,再拉高总线IO口改为输入模式延时12us读取电平,延时50us。
典型的读取温度过程是:
复位->发送SKIP ROM命令(0XCC)->发温度转换命令(0X44)->延时->复位->发送SKIP ROM命令(0XCC)->发读储存器命令(0XBE)->连续读出两个字节的数据(温度)->结束
转换后数据储存在两个八比特的ROM中,前面五个位是符号位。如果温度大于零则这五个位为零,直接将得到的数值乘上0.0625得到实际温度。温度为负,则前五位为1,需要将得到的数值取反之后乘上0.625,来得到实际温度。
下面的代码的几点说明:
单总线通信对时序有着严格的要求,所以延时函数一定要准确,这里的延时函数使用SysTick来实现;
在读和写的时候需要改变引脚的模式,这里在头头文件有说明,其实可以用位带操作来变换IO口的模式及输入输出,但是位带操作配置比较麻烦所以就直接调用库函数了,再头文件中是用空间换取了时间。
#ifndef __ds18_
#define __ds18_
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#define DQ_IO_OUT() {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=3<<0;}
#define DQ_IO_IN() {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=8<<0;}
#define DQ_OUT_H GPIO_SetBits(GPIOA,GPIO_Pin_0);
#define DQ_OUT_L GPIO_ResetBits(GPIOA,GPIO_Pin_0);
#define DQ_IN GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
void DS18B20_Init(void);
short DS18B20_Get_Temp(void);
void DS18B20_Write_Byte(u8 dat);
u8 DS18B20_Read_Byte(void);
void DS18B20_Rst(void);
#endif
#include "ds18b20.h"
#include "delay.h"
void DS18B20_Rst(void)
{
u8 flag=1;
while(flag)
{
while(flag)
{
DQ_IO_OUT();
DQ_OUT_L
delay_us(750);
DQ_OUT_H
delay_us(15);
DQ_IO_IN();
flag=DQ_IN;
}
delay_us(500);
flag=~DQ_IN;
}
DQ_IO_OUT();
DQ_OUT_H
}
void DS18B20_Write_Byte(u8 dat)
{
u8 i;
DQ_IO_OUT();
for (i=8;i>0;i--)
{
if(dat&0x01)
{
DQ_OUT_L
delay_us(2);
DQ_OUT_H
delay_us(60);
}
else
{
DQ_OUT_H
delay_us(2);
DQ_OUT_L
delay_us(60);
}
dat=dat>>1;
}
}
u8 DS18B20_Read_Byte(void)
{
u8 i;
u8 value=0;
for (i=8;i>0;i--)
{
value<<=1;
DQ_IO_OUT();
DQ_OUT_L
delay_us(2);
DQ_OUT_H
DQ_IO_IN();
delay_us(12);
value=value|DQ_IN;
delay_us(50);
}
return(value);
}
void DS18B20_Init(void)
{
GPIO_InitTypeDef GPIO_InitSturct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitSturct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitSturct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitSturct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitSturct);
}
short DS18B20_Get_Temp(void)
{
short temp;
u8 TL,TH;
DS18B20_Rst();
delay_ms(3);
DS18B20_Write_Byte(0xcc);
DS18B20_Write_Byte(0x44);
DS18B20_Rst();
delay_us(166);
DS18B20_Write_Byte(0xcc);
DS18B20_Write_Byte(0xbe);
TL=DS18B20_Read_Byte();
TH=DS18B20_Read_Byte();
temp=TH;
temp<<=8;
temp=temp|TL;
if(temp>0x0fff)
{
temp=~temp;
temp++;
temp=(unsigned int)(temp*6.25+0.5);
temp|=0xc000;
}
else
temp=(unsigned int)(temp*6.25+0.5);
return(temp);
}
TFT-LCD显示
2正点原子生产的2.8TFT显示屏(控制器为ILI9341)的操作方法:
主要有以下这些信号线:
CS:TFTLCD 片选信号。
WR:向 TFTLCD 写入数据。
RD:从 TFTLCD 读取数据。
D[15:0]:16 位双向数据线。
RST:硬复位 TFTLCD。
RS:命令/数据标志(0,读写命令;1,读写数据)。
ILI9341自带显存,在16位的模式使用RGB565的颜色格式,该控制器的命令都是8位的,除了颜色数据其他参数都是八位。
一些常用的指令:
0XD3:此命令用于读取控制器ID;
0X36:用来控制储存器的读写方向;
控制高三位,我们可以灵活的控制显示方向。
0 0 0 从左到右,从上到下 1 0 0 从左到右,从下到上
0 1 0 从右到左,从上到下 1 1 0 从右到左,从下到上
0 0 1 从上到下,从左到右 0 1 1 从上到下,从右到左
1 0 1 从下到上,从左到右 1 1 1 从下到上从右
0X2A:列地址设置指令,在从左到右,从上到下的扫描方式下(默认)该指令用于设置横轴X坐标。它有四个参数实际上是两个坐标值—列地址的起始SC和结束值SE。起始值必须小于结束值。
0X2B:页(行)地址设置指令,设置(Y坐标)和列指令相似SP—SE。一般情况下结束值只需要设置一次就可以了,不需要频繁设置。
0X2C:写GRAM指令,GRAM可以理解为对应坐标的颜色数据储存器。每写入一个值GRAM的坐标会自动沿着扫描方向加1,
0X2E:读显存指令,可以读到对应坐标点的颜色数据,每次输出两个颜色分量,第一次输出R1G1,随后的规律为:B1R2->G2B2->R3G3->B3R4->G4B4->R5G5等。
TFT的使用流程:
初始化TFT;设置坐标;写入GRAM;写入颜色;通过函数将字符与数字显示到LCD上;
下面的程序有基础的进行读写操作,也有显示一些图片和汉字的方法,显示图片或者数字是需要字模数组的,另外TFT的LCD控制器有各种型号,我用的型号为ILI9341。不同的控制器指令是不同的,应该从数据手册进行查找。ILI9341的初始化函数比较的放在了程序的后面。
时间有限代码就没有一一做注释了,本来是有注释的但是奈何一开始没有注意编码格式中文会乱码。这里就直接删了。
include "lcd.h"
#include "16x8.h"
#include "chinese.h"
#include "delay.h"
u8 L=25,H=30,a=0,made=0;
unsigned char zhizhen[]=
{
0x10,0x38,0x7C,0xFE, 0x38,0x38,0x38,0x38,
};
_lcd_dev lcddev;
//写命令
void LCD_WR_REG(u16 data)
{
LCD_RS_CLR;//
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
//写入数据
void LCD_WR_DATA(u16 data)
{
LCD_RS_SET;
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
void LCD_WR_DATAX(u16 data)
{
LCD_RS_SET;
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
/**显示窗口**/
void LCD_setwindow(unsigned int stx,unsigned int sty,unsigned int endx,unsigned int endy)
{//
LCD_WR_REG(0x2A); //
LCD_WR_DATA(stx>>8);
LCD_WR_DATA(stx&0xff);
LCD_WR_DATA(endx>>8);
LCD_WR_DATA(endx&0xff);
LCD_WR_REG(0x2B); //
LCD_WR_DATA(sty>>8);
LCD_WR_DATA(sty&0xff);
LCD_WR_DATA(endy>>8);
LCD_WR_DATA(endy&0xff);
LCD_WR_REG(0x2C); //
}
void write_data_u16(unsigned int color)//
{
LCD_RS_SET; //RS=1;
LCD_CS_CLR; //CS=0;
DATAOUT(color)
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
void scan()
{
LCD_WR_REG(0x36);
LCD_WR_DATA(0);
}
/**清屏**/
void GUI_clearscreen(short b_color)
{
short i,j;
LCD_setwindow(0,0,240,320);
for (i=0;i<320;i++)
{
for(j=0;j<240;j++)
write_data_u16(b_color);
}
}
/***写入颜色数据***/
void write_cmd_data (unsigned char cmd,unsigned int dat)
{
LCD_WR_REG(cmd);
LCD_WR_DATA(dat);
}
/***设置显示起点***/
void LCD_setxy(unsigned char x,unsigned int y)
{
LCD_setwindow(x,y,x,y);
}
/**显示点**/
void GUI_Point(u8 x, short y, short color)
{
LCD_setxy(x,y);
write_data_u16(color);
}
/**画横线**/
void GUI_HLine(u8 x, short y, u8 length, short color)
{
LCD_setwindow(x,y,x+length-1,y);
do
{
write_data_u16(color);//
length--;
}while(length);
}
/**画竖线**/
void GUI_RLine(u8 x,short y, short high, short color)
{
LCD_setwindow(x,y,x,y+high-1);
do
{
write_data_u16(color);//
high--;
}while(high);
}
/****画线****/
void GUI_line(short x1,short y1,short x2,short y2,short color)
{
short t;
int xerr=0,yerr=0,delta_x,delta_y,distance;
int incx,incy;
short row,col;
delta_x = x2-x1;//
delta_y = y2-y1;
col=x1;
row=y1;
if(delta_x>0) incx=1;//
else
{
if(delta_x==0) incx=0;//
else {incx=-1;delta_x=-delta_x;}
}
if(delta_y>0)incy=1;
else
{
if(delta_y==0) incy=0;//
else {incy=-1;delta_y=-delta_y;}
}
if(delta_x>delta_y) distance=delta_x;//
else distance=delta_y;
for(t=0;t<=distance+1;t++)
{ //
GUI_Point(col, row, color);
xerr+=delta_x;
yerr+=delta_y;
if(xerr>distance)
{
xerr-=distance;
col+=incx;
}
if(yerr>distance)
{
yerr-=distance;
row+=incy;
}
}
}
/**显示字符**/
void GUI_sprintf_char(u8 x, short y,u8 c, short color,short b_color)
{
u8 s_x ,s_y, temp ;
short j;
c -= 32;
for( s_y=0 ; s_y < 16 ; s_y++ )
{
if(s_y+y<320)
{
j=c;
j=j*16+s_y;
temp=font16x8[j];
//temp = font16x8[c*16+s_y] ;
for( s_x=0 ; s_x<8 ; s_x++ )
{
if(x+s_x<240)
{
if((temp&(0x80>>(s_x))) == (0x80>>(s_x)) )
{
GUI_Point(x+s_x, y+s_y,color) ;
}
else
{
GUI_Point(x+s_x, y+s_y,b_color) ;
}
}
}
}
}
}
/****显示字符串****/
void GUI_sprintf_string(u8 x, short y,char *s, short color,short b_color)
{
for(;*s!='\0';s++)
{
GUI_sprintf_char(x, y,*s, color,b_color);
x=x+8;
}
}
/****显示汉字****/
void GUI_sprintf_HZ(u8 x, short y, short color,short b_color)
{
u8 s_x=0 ,s_y=0, temp=0 ;
u8 n;
short j,words;
words=sizeof(china_char_1)/63;
for( n=0 ; n<words ; n++ )
{
for( s_x=0 ; s_x<21 ; s_x++ )//
{
if(s_x+x<240)
{
j=n;
j=j*63+s_x;
temp = china_char_1[j] ;
//temp = china_char[n*32+s_x] ;
for( s_y=0 ; s_y<8 ; s_y++ )
{
if(y+s_y<320)
{
if((temp&(0x80>>(s_y))) == (0x80>>(s_y)) )
{
GUI_Point(x+s_x+n*21, y+s_y,color) ;
}
else
{
GUI_Point(x+s_x+n*21, y+s_y,b_color) ;
}
}
}
}
}
for( s_x=0 ; s_x<21 ; s_x++ ) //???????
{
if(s_x+x<240)
{
j=n;
j=j*63+s_x+21;
temp = china_char_1[j] ;
//temp = china_char[n*32+s_x+16] ;
for( s_y=0 ; s_y<8 ; s_y++ )
{
if(y+s_y<320)
{
if((temp&(0x80>>(s_y))) == (0x80>>(s_y)) )
{
GUI_Point(x+s_x+n*21, y+s_y+8,color) ;
}
else
{
GUI_Point(x+s_x+n*21, y+s_y+8,b_color) ;
}
}
}
}
}
for( s_x=0 ; s_x<21 ; s_x++ ) //???????
{
if(s_x+x<240)
{
j=n;
j=j*63+s_x+42;
temp = china_char_1[j] ;
//temp = china_char[n*32+s_x+16] ;
for( s_y=0 ; s_y<8 ; s_y++ )
{
if(y+s_y<320)
{
if((temp&(0x80>>(s_y))) == (0x80>>(s_y)) )
{
GUI_Point(x+s_x+n*21, y+s_y+16,color) ;
}
else
{
GUI_Point(x+s_x+n*21, y+s_y+16,b_color) ;
}
}
}
}
}
}
}
void GUI_box(u8 sx,short sy,u8 ex,short ey,short color)
{
short temp;
LCD_setwindow(sx,sy,ex,ey);
sx=ex-sx+1;
sy=ey-sy+1;
while(sx--)
{
temp=sy;
while(temp--)
{
write_data_u16(color);
}
}
}
void LCD_WriteReg(u16 LCD_Reg,u16 LCD_RegValue)
{
LCD_WR_REG(LCD_Reg);
LCD_WR_DATA(LCD_RegValue);
}
void LCD_Scan_Dir()
{
u16 regval=0;
u16 dirreg=0;
regval|=(0<<7)|(0<<6)|(0<<5);
dirreg=0X36;
LCD_WriteReg(dirreg,regval);
}
void Shua_png()
{
GUI_box(28,60,58,285-5*H,RED);
GUI_box(28,285-5*H,58,285-5*L,GREEN);
GUI_box(28,285-5*L,58,235,BLUE);
}
void sprintf_zhizhen(u8 x, unsigned int y, unsigned int color)
{
u8 s_x=0 ,s_y=0, str=0;
unsigned int m=0;
u8 j=0,n=0;
Shua_png();
for(m=35;m<=285;m=m+5)
{
if ((m-35)%25!=0) //????
GUI_HLine(28, m, 4,0);
else
GUI_HLine(28, m, 8,0);
}
GUI_HLine(28, 285, 31,0);
for(n=28;n<=58;n=n+30)
{
GUI_RLine(n, 35, 250,0); //????
}
for( s_x=0 ; s_x<8 ; s_x++ )
{
if(s_x+x<240)
{
j=j+s_x;
str=zhizhen[j] ;
for( s_y=0 ; s_y<8 ; s_y++ )
{
if((y+s_y<285-5*H)&&(y+s_y>35))//y????????
{
if((str&(0x80>>(s_y))) == (0x80>>(s_y)) )
{
GUI_Point(x+s_x, y+s_y,color) ;
}
else
{
GUI_Point(x+s_x, y+s_y,RED) ;
}
}
else if((y+s_y>285-5*H)&&(y+s_y<285-5*L))
{
if((str&(0x80>>(s_y))) == (0x80>>(s_y)) )
{
GUI_Point(x+s_x, y+s_y,color) ;
}
else
{
GUI_Point(x+s_x, y+s_y,GREEN) ;
}
}
else if((y+s_y>285-5*L)&&(y+s_y<285))
{
if((str&(0x80>>(s_y))) == (0x80>>(s_y)) )
{
GUI_Point(x+s_x, y+s_y,color) ;
}
else
{
GUI_Point(x+s_x, y+s_y,BLUE) ;
}
}
else
{
if((str&(0x80>>(s_y))) == (0x80>>(s_y)) )
{
GUI_Point(x+s_x, y+s_y,color) ;
}
else
{
GUI_Point(x+s_x, y+s_y,YELLOW) ;
}
}
}
}
}
}
void LCD_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);//
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6; //
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure); //GPIOC
GPIO_SetBits(GPIOC,GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //
GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIOB
GPIO_SetBits(GPIOB,GPIO_Pin_All);
delay_ms(50); // delay 50 ms
LCD_WR_REG(0xCF);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0xC1);
LCD_WR_DATAX(0X30);
LCD_WR_REG(0xED);
LCD_WR_DATAX(0x64);
LCD_WR_DATAX(0x03);
LCD_WR_DATAX(0X12);
LCD_WR_DATAX(0X81);
LCD_WR_REG(0xE8);
LCD_WR_DATAX(0x85);
LCD_WR_DATAX(0x10);
LCD_WR_DATAX(0x7A);
LCD_WR_REG(0xCB);
LCD_WR_DATAX(0x39);
LCD_WR_DATAX(0x2C);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x34);
LCD_WR_DATAX(0x02);
LCD_WR_REG(0xF7);
LCD_WR_DATAX(0x20);
LCD_WR_REG(0xEA);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_REG(0xC0); //Power control
LCD_WR_DATAX(0x1B); //VRH[5:0]
LCD_WR_REG(0xC1); //Power control
LCD_WR_DATAX(0x01); //SAP[2:0];BT[3:0]
LCD_WR_REG(0xC5); //VCM control
LCD_WR_DATAX(0x30); //3F
LCD_WR_DATAX(0x30); //3C
LCD_WR_REG(0xC7); //VCM control2
LCD_WR_DATAX(0XB7);
LCD_WR_REG(0x36); // Memory Access Control
LCD_WR_DATAX(0x48);
LCD_WR_REG(0x3A);
LCD_WR_DATAX(0x55);
LCD_WR_REG(0xB1);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x1A);
LCD_WR_REG(0xB6); // Display Function Control
LCD_WR_DATAX(0x0A);
LCD_WR_DATAX(0xA2);
LCD_WR_REG(0xF2); // 3Gamma Function Disable
LCD_WR_DATAX(0x00);
LCD_WR_REG(0x26); //Gamma curve selected
LCD_WR_DATAX(0x01);
LCD_WR_REG(0xE0); //Set Gamma
LCD_WR_DATAX(0x0F);
LCD_WR_DATAX(0x2A);
LCD_WR_DATAX(0x28);
LCD_WR_DATAX(0x08);
LCD_WR_DATAX(0x0E);
LCD_WR_DATAX(0x08);
LCD_WR_DATAX(0x54);
LCD_WR_DATAX(0XA9);
LCD_WR_DATAX(0x43);
LCD_WR_DATAX(0x0A);
LCD_WR_DATAX(0x0F);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_REG(0XE1); //Set Gamma
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x15);
LCD_WR_DATAX(0x17);
LCD_WR_DATAX(0x07);
LCD_WR_DATAX(0x11);
LCD_WR_DATAX(0x06);
LCD_WR_DATAX(0x2B);
LCD_WR_DATAX(0x56);
LCD_WR_DATAX(0x3C);
LCD_WR_DATAX(0x05);
LCD_WR_DATAX(0x10);
LCD_WR_DATAX(0x0F);
LCD_WR_DATAX(0x3F);
LCD_WR_DATAX(0x3F);
LCD_WR_DATAX(0x0F);
LCD_WR_REG(0x2B);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x01);
LCD_WR_DATAX(0x3f);
LCD_WR_REG(0x2A);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0xef);
LCD_WR_REG(0x11); //Exit Sleep
delay_ms(120);
LCD_WR_REG(0x29); //display on
}