? 1. 項目簡介
這是基于STM32設計的一個指針式電子鐘+萬年歷小項目,采用3.5寸的LCD屏顯示時鐘,日歷、溫度、天氣,支持觸摸屏調整設置時間,設置鬧鐘,查看日歷等等。整體項目主要是技術點就是LCD屏的圖形繪制。比如: 時鐘的時針繪制、分針、秒針、表盤、日歷繪制等等。
時鐘的時間是直接采用STM32本身的RTC時鐘,室內的室溫數據采用DS18B20溫度傳感器獲取,STM32芯片的具體型號是STM32F103ZET6,只要是STM32F1系列的開發板,代碼都是可以通用的。
LCD顯示屏采用的正點原子的3.5寸TFT顯示屏,支持8080時序,自帶觸摸屏功能,觸摸屏是電阻屏,驅動芯片是XPT2046,SPI接口,通信非常方便。
STM32F103ZET6帶有FSMC功能,可以輸出8080時序,本項目里驅動LCD屏就采用FSMC控制的,效率比較高。
主界面如下:
?
2. 項目功能介紹
下面對每個子功能頁面做詳細講解。
2.1 實時時鐘頁面
在LCD屏上方顯示表盤、分針、時針、 秒針、刻度、更改時鐘時間方塊,并實現分針、時針、秒針的移動,在實時時鐘下方同步顯示數字時鐘。
?
運用觸摸屏功能實現時鐘設置功能,點擊“+” “-”至設置時鐘方塊,跳出設置時鐘界面,即可開始設置時鐘與日期;點擊“+”“-”至設置鬧鐘方塊,跳出設置鬧鐘界面,即可開始設置鬧鐘。
?
2.2 日歷頁面
在LCD屏中部顯示日期、星期、天氣、實時溫度,在LCD屏下方顯示日歷、左右兩邊顯示黃歷,并在日歷上重點突出今天的日期。
?
3. 項目實現主要程序講解
3.1 流程圖
?
3.2 ds18b2.c 代碼
下面列出DS18B20溫度傳感器主要代碼.
#include "ds18b20.h"
#include "delay.h"
?
//復位DS18B20
void DS18B20_Rst(void)
{
DS18B20_IO_OUT(); //SET PG11 OUTPUT
DS18B20_DQ_OUT=0; //拉低DQ
DelayUs(750); //拉低750us
DS18B20_DQ_OUT=1; //DQ=1
DelayUs(15); //15US
}
//等待DS18B20的回應
//返回1:未檢測到DS18B20的存在
//返回0:存在
u8 DS18B20_Check(void)
{
u8 retry=0;
DS18B20_IO_IN(); //SET PG11 INPUT
while (DS18B20_DQ_IN&&retry<200)
{
retry++;
DelayUs(1);
};
if(retry>=200)return 1;
else retry=0;
while (!DS18B20_DQ_IN&&retry<240)
{
retry++;
DelayUs(1);
};
if(retry>=240)return 1;
return 0;
}
//從DS18B20讀取一個位
//返回值:1/0
u8 DS18B20_Read_Bit(void)
{
u8 data;
DS18B20_IO_OUT(); //SET PG11 OUTPUT
DS18B20_DQ_OUT=0;
DelayUs(2);
DS18B20_DQ_OUT=1;
DS18B20_IO_IN(); //SET PG11 INPUT
DelayUs(12);
if(DS18B20_DQ_IN)data=1;
else data=0;
DelayUs(50);
return data;
}
//從DS18B20讀取一個字節
//返回值:讀到的數據
u8 DS18B20_Read_Byte(void)
{
u8 i,j,dat;
dat=0;
for (i=1;i<=8;i++)
{
? ? ? ?j=DS18B20_Read_Bit();
? ? ? ?dat=(j<<7)|(dat>>1);
}
return dat;
}
//寫一個字節到DS18B20
//dat:要寫入的字節
void DS18B20_Write_Byte(u8 dat)
{
u8 j;
u8 testb;
DS18B20_IO_OUT(); //SET PG11 OUTPUT;
for (j=1;j<=8;j++)
{
? ? ? ?testb=dat&0x01;
? ? ? ?dat=dat>>1;
if (testb)
{
DS18B20_DQ_OUT=0; // Write 1
DelayUs(2);
DS18B20_DQ_OUT=1;
DelayUs(60);
}
else
{
DS18B20_DQ_OUT=0; // Write 0
DelayUs(60);
DS18B20_DQ_OUT=1;
DelayUs(2);
}
}
}
//開始溫度轉換
void DS18B20_Start(void)
{
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc); // skip rom
DS18B20_Write_Byte(0x44); // convert
}
//初始化DS18B20的IO口 DQ 同時檢測DS的存在
//返回1:不存在
//返回0:存在
u8 DS18B20_Init(void)
{
RCC->APB2ENR|=1<<8; ? //使能PORTG口時鐘
GPIOG->CRH&=0XFFFF0FFF; //PORTG.11 推挽輸出
GPIOG->CRH|=0X00003000;
GPIOG->ODR|=1<<11; ? ? //輸出1
DS18B20_Rst();
return DS18B20_Check();
} ?
//從ds18b20得到溫度值
//精度:0.1C
//返回值:溫度值 (-550~1250)
short DS18B20_Get_Temp(void)
{
? ?u8 temp;
? ?u8 TL,TH;
short tem;
? ?DS18B20_Start (); // ds1820 start convert
? ?DS18B20_Rst();
? ?DS18B20_Check();
? ?DS18B20_Write_Byte(0xcc); // skip rom
? ?DS18B20_Write_Byte(0xbe); // convert ? ?
? ?TL=DS18B20_Read_Byte(); // LSB ?
? ?TH=DS18B20_Read_Byte(); // MSB ?
? ?
? ?if(TH>7)
{
TH=~TH;
TL=~TL;
temp=0; //溫度為負
}else temp=1; //溫度為正
tem=TH; //獲得高八位
tem<<=8; ? ?
? ?tem+=TL; //獲得底八位
? ?tem=(float)tem*0.625; //轉換 ? ?
if(temp)return tem; //返回溫度值
else return -tem; ? ?
}
3.3 lcd屏圖形繪制核心算法
整個項目的功能都是在LCD顯示屏上,需要繪制線段、繪制圓、繪制矩形、繪制角度線段、繪制中文、繪制數字等等,下面列出這部分的核心代碼。
/*
函數功能:畫橫直線
函數形參:x,y:坐標
? ? ? ?length:長度
*/
void LcdDrawThwartLine(u16 x,u16 y,u16 length,u16 color)
{
u16 i;
for(i=0;i0)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++ )//畫線輸出
{ ?
LcdDrawPoint(uRow,uCol,color);//畫點
xerr+=delta_x ;
yerr+=delta_y ;
if(xerr>distance)
{
xerr-=distance;
uRow+=incx;
}
if(yerr>distance)
{
yerr-=distance;
uCol+=incy;
}
}
}
?
?
//在指定位置畫一個指定大小的圓
//(x,y):中心點
//r :半徑
void LcdDraw_Circle(u16 x0,u16 y0,u8 r,u16 color)
{
int a,b;
int di;
a=0;b=r;
di=3-(r<<1); ? ? ? ? ? ? //判斷下個點位置的標志
while(a<=b)
{
LcdDrawPoint(x0+a,y0-b,color); ? ? ? ? ? ? //5
LcdDrawPoint(x0+b,y0-a,color); ? ? ? ? ? ? //0 ? ? ? ? ?
LcdDrawPoint(x0+b,y0+a,color); ? ? ? ? ? ? //4 ? ? ? ? ? ? ?
LcdDrawPoint(x0+a,y0+b,color); ? ? ? ? ? ? //6
LcdDrawPoint(x0-a,y0+b,color); ? ? ? ? ? ? //1 ? ? ?
LcdDrawPoint(x0-b,y0+a,color); ? ? ? ? ? ?
LcdDrawPoint(x0-a,y0-b,color); ? ? ? ? ? ? //2 ? ? ? ? ? ?
LcdDrawPoint(x0-b,y0-a,color); ? ? ? ? ? ? //7 ? ? ? ? ? ?
a++;
//使用Bresenham算法畫圓 ? ?
if(di<0)di +=4*a+6; ?
else
{
di+=10+4*(a-b); ?
b--;
} ? ?
}
}
?
/*
函數功能:任意角度畫直線
參 ? 數:
w :以圓心開始不要畫的長度
len:半徑
c :顏色
x,y:坐標
實際長度=len-w
*/
?
void LcdDrawAngleLine(u32 x,u32 y,float du,u32 len,u32 w,u16 c)
{
?int i;
int x0,y0;
float k=du*(3.1415926535/180);
for(i=len-w;i;i++)>;i++)>
審核編輯:湯梓紅
?
-
傳感器
+關注
關注
2552文章
51320瀏覽量
755323 -
顯示屏
+關注
關注
28文章
4504瀏覽量
74509 -
STM32
+關注
關注
2270文章
10918瀏覽量
356821
發布評論請先 登錄
相關推薦
評論