久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標題:
12864顯示模擬時鐘源碼
[打印本頁]
作者:
liu51hei3
時間:
2018-5-8 13:30
標題:
12864顯示模擬時鐘源碼
在12864上顯示一個時鐘,通過時鐘模塊的控制使得時鐘秒針一次轉動。可調節時間。
單片機源程序如下:
/*******************************************************************************************************/
//程序說明:本程序為12864(st7920)驅動程序,只實現了最簡單的顯示功能
/*******************************************************************************************************/
#include<reg52.h>
#include<intrins.h> //內含-NOP-函數
#include<stdlib.h> //內含rand()函數
#include<math.h>
#include"ds1302.h"
#define uchar unsigned char
#define uint unsigned int
//**********宏定義所需指令
#define BASIC_SET 0x30
#define EXTEND_SET 0x34
#define DRAW_ON 0x36
#define DRAW_OFF 0x34
#define PI 3.14
//*************端口定義
sbit LCD_RS = P3^5;
sbit LCD_RW = P3^6;
sbit LCD_EN = P3^4;
sbit wela = P2^6;
sbit dula = P2^7;
//************變量定義
//****************短延時
void delay(uint k)
{
uint i;
uchar j;
for(i = 0; i < k ;i ++)
for(j = 0; j < 5 ;j ++);
}
void check_busy()//判忙
{
uchar busy;
P0=0xff;
LCD_RS=0;
LCD_RW=1;
do
{
LCD_EN=1;
busy=P0;
LCD_EN=0;
}while(busy&0x80);
LCD_EN=0;
}
//***********12864寫指令函數
void write_com(uchar cmd)
{
check_busy();
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
P0 = cmd;
delay(50);
LCD_EN = 1;
delay(50);
LCD_EN = 0;
}
//********12864寫數據函數
void write_dat(uchar dat)
{
check_busy();
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
delay(5);
LCD_EN = 1;
delay(5);
LCD_EN = 0;
}
//****************從LCD中讀數據
uchar read_dat(void)
{
uchar temp;
check_busy();
P0 = 0XFF; //釋放數據線
LCD_RS = 1; //數據
LCD_RW = 1; //讀模式
LCD_EN = 1; //為高電平進行讀數據或指令
delay(1);
temp = P0;
LCD_EN = 0;
return temp;
}
//********************************************************
//設置光標(地址)函數
//參數說明:x---為行號,y為列號
//********************************************************
void set_cursor(unsigned char x, unsigned char y)
{
unsigned char i;
switch(x) //確定行號
{
case 0x00: i=0x80; break; //第一行
case 0x01: i=0x90; break; //第二行
case 0x02: i=0x88; break; //第三行
case 0x03: i=0x98; break; //第四行
default : break;
}
i = y+i; //確定列號
write_com(i);
}
//********************************************************
//顯示字符函數
//********************************************************
void display_char(unsigned char Alphabet)
{
write_dat(Alphabet); //寫入需要顯示字符的顯示碼
}
//********************************************************
//指定位置顯示字符串函數
//參數說明:x為行號,y為列號
//********************************************************
void display_string(unsigned char x,unsigned char y,unsigned char *Alphabet)
{
unsigned char i=0;
set_cursor(x,y); //設置顯示的起始地址
while(Alphabet[i]!='\0')
{
write_dat(Alphabet[i]); //寫入需要顯示字符的顯示碼
i++;
}
}
//***********************************以下為GDRAM繪圖部分****************************//
//********繪圖顯示的清屏函數(因清屏指令在畫圖時不能用)-----注意!!!!!!!
void gui_clear()
{
uchar i , j , k;
write_com(EXTEND_SET);//擴展指令集,8位數據傳輸
write_com(DRAW_OFF);//繪圖顯示關閉
for(i = 0; i < 2; i ++)//分上下兩屏寫
{
for(j = 0; j < 32; j ++)
{
write_com(0x80 + j);//寫y坐標
delay(1);
if(i == 0) //寫x坐標
{
write_com(0x80);
delay(1);
}
else //寫下半屏
{
write_com(0x88);
delay(1);
}
for(k = 0; k < 16; k ++)//寫一整行數據
{
write_dat(0x00);//寫高字節
write_dat(0x00);//寫低字節
delay(1);
}
}
}
write_com(DRAW_ON);//打開繪圖顯示
write_com(BASIC_SET);//打開基本指令集
}
//*************************************************************************************************
//***************有反白顯示功能的打點函數**********************************************************
//參數:color=1,該點填充1;color=0,該點填充白色0;
//*************************************************************************************************
void GUI_Point(unsigned char x,unsigned char y,unsigned char color)
{
unsigned char x_Dyte,x_byte; //定義列地址的字節位,及在字節中的哪1位
unsigned char y_Dyte,y_byte; //定義為上下兩個屏(取值為0,1),行地址(取值為0~31)
unsigned char GDRAM_hbit,GDRAM_lbit;
write_com(0x36); //擴展指令命令
write_com(DRAW_OFF);//繪圖顯示關閉
/***X,Y坐標互換,即普通的X,Y坐標***/
x_Dyte=x/16; //計算在16個字節中的哪一個
x_byte=x&0x0f; //計算在該字節中的哪一位
y_Dyte=y/32; //0為上半屏,1為下半屏
y_byte=y&0x1f; //計算在0~31當中的哪一行
write_com(0x80+y_byte); //設定行地址(y坐標),即是垂直地址
write_com(0x80+x_Dyte+8*y_Dyte); //設定列地址(x坐標),并通過8*y_Dyte選定上下屏,即是水平地址
read_dat(); //預讀取數據
GDRAM_hbit= read_dat(); //讀取當前顯示高8位數據
GDRAM_lbit= read_dat(); //讀取當前顯示低8位數據
delay(1);
write_com(0x80+y_byte); //設定行地址(y坐標)
write_com(0x80+x_Dyte+8*y_Dyte); //設定列地址(x坐標),并通過8*y_Dyte選定上下屏
delay(1);
if(x_byte<8) //判斷其在高8位,還是在低8位
{
if(color==1)
{
write_dat(GDRAM_hbit|(0x01<<(7-x_byte))); //置位GDRAM區高8位數據中相應的點
}
else
write_dat(GDRAM_hbit&(~(0x01<<(7-x_byte)))); //清除GDRAM區高8位數據中相應的點
write_dat(GDRAM_lbit); //顯示GDRAM區低8位數據
}
else
{
write_dat(GDRAM_hbit);
if(color==1)
write_dat(GDRAM_lbit|(0x01<<(15-x_byte))); //置位GDRAM區高8位數據中相應的點
else
write_dat(GDRAM_lbit&(~(0x01<<(15-x_byte))));//清除GDRAM區高8位數據中相應的點
}
write_com(DRAW_ON); //打開繪圖顯示
write_com(0x30); //恢復到基本指令集
}
//***********(給定坐標并打點的)任意位置打點函數
void lcd_set_dot(uchar x,uchar y)
{
uchar x_byte,x_bit;//確定在坐標的那一字節哪一位
uchar y_ping , y_bit;//確定在坐標的哪一屏哪一行
uchar tmph , tmpl;//定義兩個臨時變量,用于存放讀出來的數據
write_com(EXTEND_SET);//擴展指令集
write_com(DRAW_OFF);//繪圖顯示關閉
x_byte = x / 16;//算出在哪一字節,注意一個地址是16位的
x_bit = x % 16;//& 0x0f;//算出在哪一位
y_ping = y / 32;//確定在上半屏還是下半屏,0代表上半屏,1代表下半屏
y_bit = y % 32;//& 0x1f;//確定在第幾行
write_com(0X80 + y_bit);//先寫垂直地址(最高位必須)
write_com(0x80 + x_byte + 8 * y_ping);//水平坐標,下半屏坐標起始地址為0x88,(+8*y_ping)就是用來確定上半屏還是下半屏
read_dat();//預讀取數據
tmph = read_dat();//讀取當前顯示高8位數據
tmpl = read_dat();//讀取當前顯示低8位數據
delay(1);
write_com(0x80 + y_bit);//讀操作會改變AC,所以重新設置一下
write_com(0x80 + x_byte + 8 * y_ping);
delay(1);
if(x_bit < 8)
{
write_dat(tmph | (0x01 << (7 - x_bit)));//寫高字節,因為坐標是從左向右的,GDRAM高位在昨,低位在右
write_dat(tmpl);//原低位數據送回
}
else
{
write_dat(tmph);//原高位數據送回
write_dat(tmpl | (0x01 << (15 - x_bit)));
}
write_com(DRAW_ON); //打開繪圖顯示
write_com(BASIC_SET);//回到基本指令集
}
//************畫水平線函數**********************************//
//x0、x1為起始點和終點的水平坐標,y為垂直坐標***************//
//**********************************************************//
void gui_hline(uchar x0, uchar x1, uchar y,color)
{
uchar bak;//用于對兩個數互換的中間變量,使x1為大值
if(x0 > x1)
{
bak = x1;
x1 = x0;
x0 = bak;
}
do
{
//lcd_set_dot(x0 , y);//從左到右逐點顯示
GUI_Point(x0,y,color);
x0 ++;
}
while(x1 >= x0);
}
//***********畫豎直線函數***********************************//
//x為起始點和終點的水平坐標,y0、y1為垂直坐標***************//
//**********************************************************//
void gui_rline(uchar x, uchar y0, uchar y1,color)
{
uchar bak;//用于對兩個數互換的中間變量,使y1為大值
if(y0 > y1)
{
bak = y1;
y1 = y0;
y0 = bak;
}
do
{
//lcd_set_dot(x , y0);//從上到下逐點顯示
GUI_Point(x,y0,color);
y0 ++;
}
while(y1 >= y0);
}
//*********任意兩點間畫直線*********************************//
//x0、y0為起始點坐標,x1、y1為終點坐標**********************//
//**********************************************************//
void gui_line(uchar x0 , uchar y0 , uchar x1 , uchar y1,color)
{
char dx;//直線x軸差值
char dy;//直線y軸差值
char dx_sym;//x軸增長方向,為-1時減值方向,為1時增值方向
char dy_sym;//y軸增長方向,為-1時減值方向,為1時增值方向
char dx_x2;//dx*2值變量,用于加快運算速度
char dy_x2;//dy*2值變量,用于加快運算速度
char di; //決策變量
if(x0 == x1)//判斷是否為垂直線
{
gui_rline(x0 , y0 , y1,color);//畫垂直線
return;
}
if(y0 == y1)//判斷是否為水平線
{
gui_hline(x0 , x1 , y0,color);//畫水平線
return;
}
dx = x1 - x0;//求取兩點之間的差值
dy = y1 - y0;
//****判斷增長方向,或是否為水平線、垂直線、點*//
if(dx > 0)//判斷x軸方向
dx_sym = 1;
else
{
if(dx < 0)
dx_sym = -1;
else
{
gui_rline(x0 , y0 , y1,color);
return;
}
}
if(dy > 0)//判斷y軸方向
dy_sym = 1;
else
{
if(dy < 0)
dy_sym = -1;
else
{
gui_hline(x0 , x1 , y0,color);
return;
}
}
/*將dx、dy取絕對值***********/
dx = dx_sym * dx;
dy = dy_sym * dy;
/****計算2倍的dx、dy值*******/
dx_x2 = dx * 1;//我改為了一倍,這樣才跟真實的兩點對應
dy_x2 = dy * 1;
/***使用bresenham法進行畫直線***/
if(dx >= dy)//對于dx>=dy,使用x軸為基準
{
di = dy_x2 - dx;
while(x0 != x1)
{
//lcd_set_dot(x0,y0);
GUI_Point(x0,y0,color);
x0 +=dx_sym;
if(di < 0)
di += dy_x2;//計算出下一步的決策值
else
{
di += dy_x2 - dx_x2;
y0 += dy_sym;
}
}
//lcd_set_dot(x0, y0);//顯示最后一點
GUI_Point(x0,y0,color);
}
else //對于dx<dy使用y軸為基準
{
di = dx_x2 - dy;
while(y0 != y1)
{
//lcd_set_dot(x0, y0);
GUI_Point(x0,y0,color);
y0 += dy_sym;
if(di < 0)
di += dx_x2;
else
{
di += dx_x2 - dy_x2;
x0 += dx_sym;
}
}
GUI_Point(x0,y0,color);
//lcd_set_dot(x0, y0);//顯示最后一點
}
}
//****************畫圓函數*********************************//
//x0、y0為圓心坐標,r為圓的半徑****************************//
//*********************************************************//
void gui_circle(uchar x0 , uchar y0 , uchar r)
{
char a , b;
char di;
if(r > 31 || r == 0)//圓大于液晶屏或者沒半徑則返回
return;
a = 0;
b = r;
di = 3 - 2 * r;//判斷下個點位置的標志
while(a <= b)
{
lcd_set_dot( x0 - b , y0 - a);//3
lcd_set_dot( x0 + b , y0 - a); //0
lcd_set_dot( x0 - a , y0 + b); //1
lcd_set_dot( x0 - b , y0 - a); //7
lcd_set_dot( x0 - a , y0 - b); //2
lcd_set_dot( x0 + b , y0 + a); //4
lcd_set_dot( x0 + a , y0 - b); //5
lcd_set_dot( x0 + a , y0 + b); //6
lcd_set_dot( x0 - b , y0 + a);
a ++;
//***使用bresenham算法畫圓********/
if(di < 0)
di += 4 * a + 6;
else
{
di += 10 + 4 * (a - b);
b --;
}
lcd_set_dot( x0 + a , y0 + b);
}
}
//****************12864初始化函數
void lcd_init()
{
write_com(0x30);//基本指令操作,8位并口
delay(1);
write_com(0x06);//設置為游標右移,DDRAM地址加一,畫面不動
delay(1);
write_com(0x0c);//顯示開,關光標
delay(1);
write_com(0x01);//清除lcd顯示內容
delay(1);
}
/***************************************************
函數名稱:LcdTimeX(uint8 Length,uint8 Angle)
函數功能:計算指針的X坐標
輸入參數:circle_x:圓心橫坐標
Length :半徑長度
Angle :角度
輸出參數: x坐標
****************************************************/
unsigned char Lcd_TimeX(unsigned char circle_x,unsigned char Length,unsigned char Angle)
{
unsigned char x;
if((Angle>0) && (Angle<=15))
{
x = circle_x + Length * (sin(PI * Angle / 30));
}
else if(Angle > 15 && Angle <= 30)
{
x = circle_x + Length * cos((PI * Angle) / 30 - (PI / 2 ));
}
else if(Angle > 30 && Angle <= 45)
{
x = circle_x - Length * sin((PI * Angle) / 30- PI);
}
else
{
x = circle_x-Length * cos((PI * Angle) / 30 - ((3 * PI) / 2));
}
return x;
}
/***************************************************
函數名稱:LcdTimeY(uint8 Length,uint8 Angle)
函數功能:計算指針的Y坐標
輸入參數:circle_y:圓心縱坐標
Length :半徑長度
Angle :角度
輸出參數: Y坐標
****************************************************/
unsigned char Lcd_TimeY(unsigned char circle_y,unsigned char Length,unsigned char Angle)
{
unsigned char y;
if((Angle>0) && (Angle<=15))
{
y = circle_y - Length * (cos(PI * Angle / 30));
}
else if(Angle > 15 && Angle <= 30)
{
y = circle_y + Length * sin((PI * Angle) / 30 - (PI / 2 ));
}
else if(Angle > 30 && Angle <= 45)
{
y = circle_y + Length * cos((PI * Angle) / 30- PI);
}
else
{
y = circle_y - Length * sin((PI * Angle) / 30 - ((3 * PI) / 2));
}
return y;
}
void init_Point_Clock() //初始化表盤
{
unsigned char i;
for(i=0;i<60;i++)
{
if((i%5)==0) //畫刻度(0,5,10,15。。。)
{
gui_line(Lcd_TimeX(32,30,i),Lcd_TimeY(32,30,i),Lcd_TimeX(32,27,i),Lcd_TimeY(32,27,i),1);
}
}
}
struct POINT_CLOCK
{
unsigned char hour;
unsigned char minute;
unsigned char second;
}Point_Time[2];
/*========================================================================
*name:Display_Pointer(struct POINT_CLOCK AA,unsigned char color)
*function:顯示時、分、秒指針
*參 數:結構體: 時分秒
* color: 0不顯示 1:顯示
*注:秒針長24
分針長17
秒針長12
=========================================================================*/
/*void Display_Pointer(struct POINT_CLOCK AA) //指針顯示
{
//Lcd_Line(Lcd_TimeX(32,24,AA.second),Lcd_TimeY(32,24,AA.second),32,32,color);
gui_line(Lcd_TimeX(32,24,AA.second),Lcd_TimeY(32,24,AA.second),32,32,1);//秒針
//Lcd_Line(Lcd_TimeX(32,17,AA.minute),Lcd_TimeY(32,17,AA.minute),32,32,color);
gui_line(Lcd_TimeX(32,17,AA.minute),Lcd_TimeY(32,17,AA.minute),32,32,1);//分針
//Lcd_Line(Lcd_TimeX(32,12,AA.minute/10+5*(AA.hour%12)),Lcd_TimeY(32,12,AA.minute/10+5*(AA.hour%12)),32,32);
gui_line(Lcd_TimeX(32,12,AA.minute/10+5*(AA.hour%12)),Lcd_TimeY(32,12,AA.minute/10+5*(AA.hour%12)),32,32,1);
//時針
}*/
void refresh()
{
if(Point_Time[0].second!=Point_Time[1].second) //秒刷新
{
gui_line(Lcd_TimeX(32,24,Point_Time[1].second),Lcd_TimeY(32,24,Point_Time[1].second),32,32,0);
……………………
…………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
12864顯示模擬時鐘.rar
(59.93 KB, 下載次數: 45)
2018-5-8 13:28 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
作者:
Johon
時間:
2018-5-10 20:45
很好,但沒顯示出來
歡迎光臨 (http://www.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
国产精品日韩欧美
|
精品一区二区三区四区五区
|
国产伦精品一区二区三区视频金莲
|
国产中文视频
|
av免费成人
|
a在线观看
|
亚洲成人在线免费
|
黄网免费看
|
91精品国产一区二区三区香蕉
|
欧美亚洲高清
|
亚洲欧美精
|
一级一级一级毛片
|
国产 日韩 欧美 在线
|
日日夜夜精品视频
|
在线91
|
国产乱一区二区三区视频
|
免费在线观看一级毛片
|
日韩午夜一区二区三区
|
久久久看
|
三级成人在线
|
天天看天天摸天天操
|
日韩欧美一区二区在线播放
|
99av成人精品国语自产拍
|
黄色网址在线免费观看
|
欧美日韩中文在线观看
|
精品一区二区三区91
|
久久成人免费
|
精品三级在线观看
|
日韩精品一区二区三区在线播放
|
九九热这里只有精品在线观看
|
成人天堂噜噜噜
|
91精品国产综合久久精品
|
欧美激情综合色综合啪啪五月
|
九九热在线观看
|
91在线最新
|
在线a视频
|
精品国产免费人成在线观看
|
一区二区三区视频在线
|
亚洲区一区二
|
不卡视频一区
|
一区二区视频在线观看
|