stm8 軟體模擬IIC驅動PCF8563T,NOKIA5110液晶顯示
阿新 • • 發佈:2019-01-29
除錯stm8硬體IIC,弄了幾天,搞得人頭大,一直程式就是卡在 while((I2C_SR1&0x02))這裡,資料手冊和網上的各種帖子基本都看了,程式都試了,ARF位也設定了,還是除錯不通,最後沒辦法只能使用軟體模擬IIC了。
這次使用軟體模擬IIC驅動PCF8563T,這個時鐘晶片。其實軟體模擬也不難。
我們就來直接看程式碼吧。具體的實驗現象,沒有圖片,現在硬體也拆了,但是程式都是驗證過了的。通過一個NOKIA5110液晶屏顯示出來時間資料。
#include "IOSTM8S105K4.h" #define u16 unsigned int #define u8 unsigned char u8 i; void delay_ms(u16 xms); void System_Init(void) { CLK_SWR = 0xE1; //選擇高速內部時鐘HSI為主時鐘 CLK_ICKR |= 0x01; //高速內部HSI時鐘使能 while(!(CLK_ICKR&0x02)); //等待內部高速HSI就緒 CLK_CKDIVR = 0x18; // Fhsi = Fhsi = Fcpu = Fmaster = 2MHz } void Timer4_init(u8 psc,u8 arr ) { CLK_PCKENR1 |= 0x10; //開啟TIM4時鐘 = Fmaster = 2MHz TIM4_EGR = 0x01; //計數器重新初始化併產生暫存器更新 TIM4_PSCR = psc; //分頻器時鐘為2MHz/psc // TIM4_CNTR = arr; //計數器值 TIM4_ARR = arr; //自動過載值 TIM4_CR1 = 0x01; //使能計數器 TIM4_IER = 0x01; //使能更新中斷 asm("rim"); //開全域性中斷 } void LCD_CLK(u8 x) { PC_DDR |= 0x08; PC_CR1 |= 0x08; PC_CR2 |= 0x00; if(x == 1) PC_ODR |= 0x08; else if(x == 0)PC_ODR &= 0xF7; } void LCD_DIN(u8 x) { PC_DDR |= 0x04; PC_CR1 |= 0x04; PC_CR2 |= 0x00; if(x == 1) PC_ODR |= 0x04; else if(x == 0)PC_ODR &= 0xFB; } void LCD_DC(u8 x) { PC_DDR |= 0x02; PC_CR1 |= 0x02; PC_CR2 |= 0x00; if(x == 1) PC_ODR |= 0x02; else if(x == 0)PC_ODR &= 0xFD; } void LCD_CE(u8 x) { PE_DDR|=0x20; PE_CR1|=0x20; PE_CR2|=0x00; if(x == 1) PE_ODR |= 0x20; else if(x == 0)PE_ODR &= 0xDF; } void LCD_RST(u8 x) { PB_DDR|=0x01; PB_CR1|=0x01; PB_CR2|=0x00; if(x == 1) PB_ODR |= 0x01; else if(x == 0)PB_ODR &= 0xFE; } void LCD_BL(u8 x) { PC_DDR|=0x10; PC_CR1|=0x10; PC_CR2|=0x00; if(x == 1) PC_ODR |= 0x10; else if(x == 0)PC_ODR &= 0xEF; } /*--------------------------------------------------------------*/ //指令巨集定義 #define X_Col_Addr 0x80 //定位到第0列指令(列起始地址)(0 - 83) #define Y_Page_Addr 0x40 //定位到第0頁指令(頁起始地址)(0 - 5) /*------------------------------------------ //資料介面定義 #define LCD_CLK PC_ODR_ODR3 //序列時鐘 //上升沿寫入資料 #define LCD_DIN PC_ODR_ODR2 //序列資料輸入 //先高後低 #define LCD_DC PC_ODR_ODR1 //資料指令控制端 //高電平資料,低電平指令 #define LCD_CS PE_ODR_ODR5 //片選使能 //低電平有效 #define LCD_RST PB_ODR_ODR0 //LCD復位端 //低電平復位 --------------------*/ /*--------------------------------------------------------------*/ //功能巨集定義 //液晶復位 #define LCD_reset_hard LCD_RST(0); delay_ms(1); LCD_RST(1);delay_ms(1) //硬體復位 #define LCD_reset_soft LCD_reset_5510() //軟體復位 //液晶顯示控制(不影響DDRAM) #define LCD_show_blank LCD_write_cmd(0x08) //顯示空白 #define LCD_show_normal LCD_write_cmd(0x0c) //正常顯示 #define LCD_show_black LCD_write_cmd(0x09) //顯示全黑 #define LCD_show_inverse LCD_write_cmd(0x0d) //反色顯示 //便於理解 #define LCD_write_cmd(cmd) LCD_write_byte(cmd, 0) //寫入指令 #define LCD_write_dat(dat) LCD_write_byte(dat, 1) //寫入資料 /*--------------------------------------------------------------*/ //函式宣告(私有) void LCD_write_byte(u8 wbyte, u8 dat_cmd);//寫入位元組 void LCD_reset_5510(void); //復位LCD5510 /*--------------------------------------------------------------*/ //函式宣告(公有) /*--------------------------------------------------------------*/ //清屏引數(清DDRAM) void LCD_clr_scr(void); /*--------------------------------------------------------------*/ //液晶位元組定位(1*1) //液晶規劃: //x: 0 - 83 //y: 0 - 5 void LCD_pos_byte(u8 x, u8 y); /*--------------------------------------------------------------*/ //顯示清行 //num: 0 - 5 void LCD_clr_row(u8 num); /*--------------------------------------------------------------*/ //液晶字元輸出(6*8字型) //x: 0 - 13 //y: 0 - 5 void LCD_printc(u8 x, u8 y, u8 c_dat); /*--------------------------------------------------------------*/ //液晶字串輸出(6*8字型) //x: 0 - 13 //y: 0 - 5 void LCD_prints(u8 x, u8 y, u8 *s_dat); /*--------------------------------------------------------------*/ //液晶字串輸出,自動換行(6*8字型) //x: 0 - 13 //y: 0 - 5 void LCD_printsl(u8 x, u8 y, u8 *s_dat); /*--------------------------------------------------------------*/ //液晶漢字輸出(16*16字型) //查表顯示輸出 //取碼規則: 低位在前, 列行掃描, 陰碼(1-亮, 0-滅) //x: 0 - 4 //y: 0 - 2 void LCD_showch(u8 x, u8 y, u8 *dat); /*--------------------------------------------------------------*/ //液晶漢字片語輸出(16*16字型) //查表顯示輸出 //取碼規則: 低位在前, 列行掃描, 陰碼(1-亮, 0-滅) //x: 0 - 4 //y: 0 - 2 //一行最多5個 void LCD_showsh(u8 x, u8 y, u8 *dat); /*--------------------------------------------------------------*/ //顯示84X48圖片 //取碼規則: 低位在前, 列行掃描, 陰碼(1-亮, 0-滅) void LCD_picture(u8 *img_dat); /*--------------------------------------------------------------*/ //定位顯示指定大小圖片 //取碼規則: 低位在前, 列行掃描, 陰碼(1-亮, 0-滅) //pag: 0 - 5 頁座標 //col: 0 - 83 列座標 //x: 0 - (83-col) 圖片寬 //y: 0 - (47-pag*8) 圖片高 void LCD_pos_picture(u8 col, u8 pag, u8 x, u8 y, u8 *img_dat); /*--------------------------------------------------------------*/ //定位輸出數字 //x: 0 - 13 //y: 0 - 5 //num: 0 - 65535 要顯示的數字 //num_u8: 0 - 5 數字的位數 void LCD_printn(u8 x, u8 y, u16 num, u8 num_u8); /*--------------------------------------------------------------*/ //初始化LCD5510 void LCD5510_Init(void); // ------------------ 漢字字模的資料結構定義 ------------------------ // typedef struct typFNT_GB16 // 漢字字模資料結構 { u8 Index[2]; // 漢字內碼索引 u8 Msk[32]; // 點陣碼資料 }typFNT_GB16; ///////////////////////////////////////////////////////////////////////// // 漢字字模表 // // 漢字型檔: 宋體16.dot 縱向取模下高位,資料排列:從左到右從上到下 // ///////////////////////////////////////////////////////////////////////// struct typFNT_GB16 GB_16[] = // 資料表 { "我", 0x20,0x24,0x24,0x24,0xFE,0x23,0x22,0x20,0xFF,0x20,0x22,0xAC,0x20,0x30,0x20,0x00, 0x00,0x08,0x48,0x84,0x7F,0x02,0x21,0x10,0x09,0x06,0x1A,0x61,0x80,0xE0,0x00,0x00, "心", 0x00,0x00,0xC0,0x00,0xF0,0x00,0x01,0x02,0x1C,0x08,0x00,0x00,0x40,0x80,0x00,0x00, 0x04,0x02,0x01,0x00,0x3F,0x40,0x40,0x40,0x40,0x40,0x40,0x70,0x00,0x00,0x07,0x00, "永", 0x00,0x40,0x40,0x48,0x48,0xC8,0x09,0xFA,0x40,0x80,0x40,0x20,0x30,0x00,0x00,0x00, 0x00,0x20,0x10,0x08,0x06,0x41,0x80,0x7F,0x00,0x01,0x06,0x08,0x10,0x30,0x10,0x00, "恆", 0x80,0x70,0x00,0xFF,0x10,0x22,0xF2,0x92,0x92,0x92,0x92,0x92,0xFB,0x12,0x00,0x00, 0x00,0x00,0x00,0xFF,0x20,0x20,0x27,0x24,0x24,0x24,0x24,0x24,0x27,0x30,0x20,0x00, "之", 0x00,0x10,0x10,0x10,0x10,0x10,0x11,0x16,0x10,0x90,0x50,0x30,0x10,0x00,0x00,0x00, 0x00,0x20,0x10,0x10,0x28,0x48,0x44,0x42,0x41,0x40,0x40,0x40,0x40,0x60,0x20,0x00, "★", 0x00,0x20,0x60,0xE0,0xE0,0xE0,0xF0,0xFC,0xFF,0xFC,0xF0,0xE0,0xE0,0xE0,0x60,0x20, 0x00,0x00,0x40,0x30,0x3D,0x1F,0x1F,0x0F,0x07,0x0F,0x1F,0x1F,0x3D,0x30,0x40,0x00 }; // 漢字表: // 我心永恆★ #define GB_16_num sizeof(GB_16) / 34 //漢字個數 /*-------------------------------------------------------------- //字型檔碼的引索 (0) !(1) "(2) #(3) $(4) %(5) &(6) '(7) ((8) )(9) *(10) +(11) ,(12) -(13) .(14) /(15) 0(16) 1(17) 2(18) 3(19) 4(20) 5(21) 6(22) 7(23) 8(24) 9(25) :(26) ;(27) <(28) =(29) >(30) ?(31) @(32) A(33) B(34) C(35) D(36) E(37) F(38) G(39) H(40) I(41) J(42) K(43) L(44) M(45) N(46) O(47) P(48) Q(49) R(50) S(51) T(52) U(53) V(54) W(55) X(56) Y(57) Z(58) [(59) \(60) ](61) ^(62) _(63) `(64) a(65) b(66) c(67) d(68) e(69) f(70) g(71) h(72) i(73) j(74) k(75) l(76) m(77) n(78) o(79) p(80) q(81) r(82) s(83) t(84) u(85) v(86) w(87) x(88) y(89) z(90) {(91) |(92) }(93) ~(94) --------------------------------------------------------------*/ /*--------------------------------------------------------------*/ // 字型: LCD1602字型 //取碼規則: 低位在前, 列行掃描, 陰碼(1-亮, 0-滅) //查表方法: 要顯示的ASCII碼-32就可以得到字型檔碼的指標 u8 Font_[][6] = { {0x00,0x00,0x00,0x00,0x00,0x00},// (0) {0x00,0x00,0x00,0x4F,0x00,0x00},//!(1) {0x00,0x00,0x07,0x00,0x07,0x00},//"(2) {0x00,0x14,0x7F,0x14,0x7F,0x14},//#(3) {0x00,0x24,0x2A,0x7F,0x2A,0x12},//$(4) {0x00,0x23,0x13,0x08,0x64,0x62},//%(5) {0x00,0x36,0x49,0x55,0x22,0x50},//&(6) {0x00,0x00,0x05,0x03,0x00,0x00},//'(7) {0x00,0x00,0x1C,0x22,0x41,0x00},//((8) {0x00,0x00,0x41,0x22,0x1C,0x00},//)(9) {0x00,0x14,0x08,0x3E,0x08,0x14},//*(10) {0x00,0x08,0x08,0x3E,0x08,0x08},//+(11) {0x00,0x00,0x50,0x30,0x00,0x00},//,(12) {0x00,0x08,0x08,0x08,0x08,0x08},//-(13) {0x00,0x00,0x60,0x60,0x00,0x00},//.(14) {0x00,0x20,0x10,0x08,0x04,0x02},///(15) {0x00,0x3E,0x51,0x49,0x45,0x3E},//0(16) {0x00,0x00,0x42,0x7F,0x40,0x00},//1(17) {0x00,0x42,0x61,0x51,0x49,0x46},//2(18) {0x00,0x21,0x41,0x45,0x4B,0x31},//3(19) {0x00,0x18,0x14,0x12,0x7F,0x10},//4(20) {0x00,0x27,0x45,0x45,0x45,0x39},//5(21) {0x00,0x3C,0x4A,0x49,0x49,0x30},//6(22) {0x00,0x01,0x71,0x09,0x05,0x03},//7(23) {0x00,0x36,0x49,0x49,0x49,0x36},//8(24) {0x00,0x06,0x49,0x49,0x29,0x1E},//9(25) {0x00,0x00,0x36,0x36,0x00,0x00},//:(26) {0x00,0x00,0x56,0x36,0x00,0x00},//;(27) {0x00,0x08,0x14,0x22,0x41,0x00},//<(28) {0x00,0x14,0x14,0x14,0x14,0x14},//=(29) {0x00,0x00,0x41,0x22,0x14,0x08},//>(30) {0x00,0x02,0x01,0x51,0x09,0x06},//?(31) {0x00,0x32,0x49,0x79,0x41,0x3E},//@(32) {0x00,0x7E,0x11,0x11,0x11,0x7E},//A(33) {0x00,0x7F,0x49,0x49,0x49,0x3E},//B(34) {0x00,0x3E,0x41,0x41,0x41,0x22},//C(35) {0x00,0x7F,0x41,0x41,0x22,0x1C},//D(36) {0x00,0x7F,0x49,0x49,0x49,0x41},//E(37) {0x00,0x7F,0x09,0x09,0x09,0x01},//F(38) {0x00,0x3E,0x41,0x49,0x49,0x7A},//G(39) {0x00,0x7F,0x08,0x08,0x08,0x7F},//H(40) {0x00,0x00,0x41,0x7F,0x41,0x00},//I(41) {0x00,0x20,0x40,0x41,0x3F,0x01},//J(42) {0x00,0x7F,0x08,0x14,0x22,0x41},//K(43) {0x00,0x7F,0x40,0x40,0x40,0x40},//L(44) {0x00,0x7F,0x02,0x04,0x02,0x7F},//M(45) {0x00,0x7F,0x04,0x08,0x10,0x7F},//N(46) {0x00,0x3E,0x41,0x41,0x41,0x3E},//O(47) {0x00,0x7F,0x09,0x09,0x09,0x06},//P(48) {0x00,0x3E,0x41,0x51,0x21,0x5E},//Q(49) {0x00,0x7F,0x09,0x19,0x29,0x46},//R(50) {0x00,0x46,0x49,0x49,0x49,0x31},//S(51) {0x00,0x01,0x01,0x7F,0x01,0x01},//T(52) {0x00,0x3F,0x40,0x40,0x40,0x3F},//U(53) {0x00,0x1F,0x20,0x40,0x20,0x1F},//V(54) {0x00,0x3F,0x40,0x38,0x40,0x3F},//W(55) {0x00,0x63,0x14,0x08,0x14,0x63},//X(56) {0x00,0x03,0x04,0x78,0x04,0x03},//Y(57) {0x00,0x61,0x51,0x49,0x45,0x43},//Z(58) {0x00,0x00,0x7F,0x41,0x41,0x00},//[(59) {0x00,0x15,0x16,0x7C,0x16,0x15},//\(60) {0x00,0x00,0x41,0x41,0x7F,0x00},//](61) {0x00,0x04,0x02,0x01,0x02,0x04},//^(62) {0x00,0x40,0x40,0x40,0x40,0x40},//_(63) {0x00,0x00,0x01,0x02,0x04,0x00},//`(64) {0x00,0x20,0x54,0x54,0x54,0x78},//a(65) {0x00,0x7F,0x48,0x44,0x44,0x38},//b(66) {0x00,0x38,0x44,0x44,0x44,0x20},//c(67) {0x00,0x38,0x44,0x44,0x48,0x7F},//d(68) {0x00,0x38,0x54,0x54,0x54,0x18},//e(69) {0x00,0x08,0x7E,0x09,0x01,0x02},//f(70) {0x00,0x0C,0x52,0x52,0x52,0x3E},//g(71) {0x00,0x7F,0x08,0x04,0x04,0x78},//h(72) {0x00,0x00,0x44,0x7D,0x40,0x00},//i(73) {0x00,0x20,0x40,0x44,0x3D,0x00},//j(74) {0x00,0x7F,0x10,0x28,0x44,0x00},//k(75) {0x00,0x00,0x41,0x7F,0x40,0x00},//l(76) {0x00,0x7E,0x02,0x0C,0x02,0x7C},//m(77) {0x00,0x7E,0x04,0x02,0x02,0x7C},//n(78) {0x00,0x38,0x44,0x44,0x44,0x38},//o(79) {0x00,0x7C,0x14,0x14,0x14,0x08},//p(80) {0x00,0x08,0x14,0x14,0x18,0x7C},//q(81) {0x00,0x7C,0x08,0x04,0x04,0x08},//r(82) {0x00,0x48,0x54,0x54,0x54,0x20},//s(83) {0x00,0x04,0x3F,0x44,0x40,0x20},//t(84) {0x00,0x3C,0x40,0x40,0x20,0x7C},//u(85) {0x00,0x1C,0x20,0x40,0x20,0x1C},//v(86) {0x00,0x3C,0x40,0x30,0x40,0x3C},//w(87) {0x00,0x44,0x28,0x10,0x28,0x44},//x(88) {0x00,0x0C,0x50,0x50,0x50,0x3C},//y(89) {0x00,0x44,0x64,0x54,0x4C,0x44},//z(90) {0x00,0x00,0x08,0x36,0x41,0x00},//{(91) {0x00,0x00,0x00,0x7F,0x00,0x00},//|(92) {0x00,0x00,0x41,0x36,0x08,0x00},//}(93) {0x00,0x08,0x04,0x08,0x10,0x08},//~(94) {0x00,0x08,0x08,0x2A,0x1C,0x08},//→(127) {0x00,0x08,0x1C,0x2A,0x08,0x08},//←(128) {0x00,0x04,0x02,0x7F,0x02,0x04},//↑(129) {0x00,0x10,0x20,0x7F,0x20,0x10},//↓(130) {0x00,0x1C,0x2A,0x32,0x2A,0x1C},//笑面(131) {0x00,0x1C,0x22,0x44,0x22,0x1C}};//愛心(132) /*--------------------------------------------------------------*/ /*延時xms函式@ HSI 2MHz*/ void delay_ms(u16 xms) { u16 i,j; for(i=xms;i>0;i--) for(j=330;j>0;j--) { asm("nop"); } } /*硬體驅動NOKIA5110液晶程式碼*/
/*void Spi_Init(void) { CLK_PCKENR1 |= 0x02; //開啟SPI時鐘 /*PC6、PC5設定為輸出,最大10MHz*/ PC_DDR = 0x70; PC_CR1 = 0x70; PC_CR2 = 0x70; /*MSB、1MHz、主裝置、CPOL空閒為低、CPHA第一個時鐘開始*/ SPI_CR1 = 0x04; /*雙線單向視距傳輸、CRC計算禁止、軟體NSS、主模式*/ SPI_CR2 = 0x03; /*開啟SPI*/ SPI_CR1|= 0x40; } void Spi_Send(u8 data) { SPI_DR = data; //再發低八位 while(!(SPI_SR&0x02)); //等待發送區為空 } /*--------------------------------------------------------------*/ //寫入一個位元組(資料或指令) //wbyte:<span style="white-space:pre"> </span>待寫入的資料 //dat_cmd:<span style="white-space:pre"> </span>1-資料, 0-指令 void LCD_write_byte(u8 wbyte, u8 dat_cmd) { LCD_CE(0);//1-資料<span style="white-space:pre"> </span>//0-指令 LCD_DC(dat_cmd); Spi_Send(wbyte); LCD_CE(1); }*/
/*--------------------------------------------------------------*/ //寫入一個位元組(資料或指令) //wbyte: 待寫入的資料 //dat_cmd: 1-資料, 0-指令 void LCD_write_byte(u8 wbyte, u8 dat_cmd) { u8 i; LCD_CE(0); //1-資料 //0-指令 LCD_DC(dat_cmd); for(i = 8; i; i--) //8位資料, 先高後低 { if(wbyte & 0x80) {//LCD_DIN = 1; LCD_DIN(1);} else {//LCD_DIN = 0; LCD_DIN(0);} LCD_CLK(0); wbyte <<= 1; //移位(延時) LCD_CLK(1); } LCD_CE(1); } /*--------------------------------------------------------------*/ //寫入n個位元組(資料)(ROM) //*wbyte: 待寫入的資料指標 //num: 待寫入的資料個數 /*void LCD_write_nbyte(u8 *wbyte, u8 num) { u8 i, j; u8 temp; LCD_CS = 0; //使能 LCD_DC = 1; //資料 for(j = 0; j < num; j++)//num個數據 { temp = wbyte[j]; for(i = 8; i; i--) //8位資料, 先高後低 { if(temp & 0x80) {LCD_DIN = 1;} else {LCD_DIN = 0;} LCD_CLK = 0; temp <<= 1; //移位(延時) LCD_CLK = 1; //上升沿寫入 } } LCD_CS = 1; //禁止 } -----------------*/ //顯示清屏(清DDRAM) void LCD_clr_scr(void) { u16 i; LCD_write_cmd(X_Col_Addr); LCD_write_cmd(Y_Page_Addr); for(i = 504; i; i--) LCD_write_dat(0x00); } //顯示清行 //num: 0 - 5 void LCD_clr_row(u8 num) { u8 i; LCD_pos_byte(0, num); for(i = 84; i; i--) LCD_write_dat(0x00); } /*--------------------------------------------------------------*/ //液晶位元組定位(1*1) //液晶規劃: //x: 0 - 83 //y: 0 - 5 void LCD_pos_byte(u8 x, u8 y) { x |= X_Col_Addr; y |= Y_Page_Addr; LCD_write_cmd(x); //列地址 LCD_write_cmd(y); //頁地址 } /*--------------------------------------------------------------*/ //液晶字元輸出(6*8字型) //x: 0 - 13 //y: 0 - 5 void LCD_printc(u8 x, u8 y, u8 c_dat) { u8 i; c_dat -= 32; //查表 x *= 6; //寬6 LCD_pos_byte(x, y); //座標 for(i = 0; i < 6; i++) LCD_write_dat(Font_[c_dat][i]); } /*--------------------------------------------------------------*/ //液晶字串輸出(6*8字型) //x: 0 - 13 //y: 0 - 5 void LCD_prints(u8 x, u8 y, u8 *s_dat) { while(*s_dat && x < 14) {LCD_printc(x++, y, *s_dat); s_dat++;} } /*--------------------------------------------------------------*/ //液晶字串輸出,自動換行(6*8字型) //x: 0 - 13 //y: 0 - 5 void LCD_printsl(u8 x, u8 y, u8 *s_dat) { while(*s_dat) { LCD_printc(x++, y, *s_dat); s_dat++; if(x == 14) {x = 0; y++;} if(y == 6) {y = 0;} } } /*--------------------------------------------------------------*/ //液晶漢字輸出(16*16字型) //取碼規則: 低位在前, 列行掃描, 陰碼(1-亮, 0-滅) //x: 0 - 4 //y: 0 - 2 void LCD_printch(u8 x, u8 y, u8 *h_dat) { u8 i, j; x <<= 4; //字寬16 y <<= 1; //字高16 for(j = 0; j < 2; j++) { LCD_pos_byte(x, (y + j)); //座標 for(i = 0; i < 16; i++) LCD_write_dat(h_dat[16 * j + i]); } } /*--------------------------------------------------------------*/ //液晶漢字輸出(16*16字型) //查表顯示輸出 //取碼規則: 低位在前, 列行掃描, 陰碼(1-亮, 0-滅) //x: 0 - 4 //y: 0 - 2 void LCD_showch(u8 x, u8 y, u8 *dat) { u8 i; for(i = 0; i < GB_16_num; i++) { if((GB_16[i].Index[0] == dat[0]) && (GB_16[i].Index[1] == dat[1])) break; } LCD_printch(x, y, GB_16[i].Msk); } /*--------------------------------------------------------------*/ //液晶漢字片語輸出(16*16字型) //查表顯示輸出 //取碼規則: 低位在前, 列行掃描, 陰碼(1-亮, 0-滅) //x: 0 - 4 //y: 0 - 2 //一行最多5個 void LCD_showsh(u8 x, u8 y, u8 *dat) { while(*dat) {LCD_showch(x++, y, dat); dat += 2;} //一個漢字GB碼由2個位元組組成 } /*--------------------------------------------------------------*/ //顯示84X48圖片 //取碼規則: 低位在前, 列行掃描, 陰碼(1-亮, 0-滅) void LCD_picture(u8 *img_dat) { u16 i; for(i = 0; i < 504; i++) LCD_write_dat(img_dat[i]); } /*--------------------------------------------------------------*/ //定位顯示指定大小圖片 //取碼規則: 低位在前, 列行掃描, 陰碼(1-亮, 0-滅) //pag: 0 - 5 頁座標 //col: 0 - 83 列座標 //x: 0 - (83-col) 圖片寬 //y: 0 - (47-pag*8) 圖片高 void LCD_pos_picture(u8 col, u8 pag, u8 x, u8 y, u8 *img_dat) { u8 i, j; y = (y + 4) >> 3; //四捨五入 for(j = 0; j < y; j++) { for(i = 0; i < x; i++) { LCD_pos_byte(col + i, pag + j); //座標 LCD_write_dat(img_dat[j * x + i]); //資料 } } } /*--------------------------------------------------------------*/ //定位輸出數字 //x: 0 - 13 //y: 0 - 5 //num: 0 - 65535 要顯示的數字 //num_u8: 0 - 5 數字的位數 void LCD_printn(u8 x, u8 y, u16 num, u8 num_u8) { signed char i; u8 ii; u8 dat[6]; for(i = 0; i < 6; i++) dat[i] = 0; //初始化資料 i = 0; while(num / 10) //拆位 { dat[i] = num % 10; //最低位 num /= 10; i++; } dat[i] = num; //最高位 ii = i; //儲存dat的位數 for(; i >= 0; i--) dat[i] += 48; //轉化成ASCII for(i = 0; i < num_u8; i++) LCD_printc(x + i, y, ' '); //清顯示區域 for(i = ii; i >= 0; i--) LCD_printc(x++, y, dat[i]); //輸出數值 } /*------------------------------------ //復位LCD5510 void LCD_reset_5510(void) { LCD_clr_scr(); //清全屏 LCD_write_cmd(0x25); //省電模式, 水平定址, 擴充套件指令 LCD_write_cmd(0x04); //VLCD溫度係數0 LCD_write_cmd(0x10); //設定偏置系統(BSx) LCD_write_cmd(0xc0); //設定電壓VLCD = 3.06 + 0.06*Vop; LCD_write_cmd(0x24); //省電模式, 水平定址, 常規指令 LCD_write_cmd(0x08); //顯示空白 LCD_write_cmd(Y_Page_Addr); //起始頁地址0 LCD_write_cmd(X_Col_Addr); //起始列地址0 } --------------------------*/ //初始化LCD5510 void LCD5510_Init(void) { LCD_reset_hard; //硬體復位 // LCD_reset_soft; //軟體復位 LCD_write_cmd(0x21); //工作模式, 水平定址, 擴充套件指令 LCD_write_cmd(0x06); //VLCD溫度係數2 LCD_write_cmd(0x13); //設定偏置系統(BSx) 1:48 LCD_write_cmd(0xc8); //設定電壓VLCD = 3.06 + 0.06*Vop, 對比度調整 LCD_write_cmd(0x20); //工作模式, 水平定址, 常規指令 LCD_write_cmd(0x0c); //普通模式 LCD_write_cmd(Y_Page_Addr); //起始頁地址0 LCD_write_cmd(X_Col_Addr); //起始列地址0 LCD_clr_scr(); //清全屏 } void Delay() { asm("nop"); asm("nop"); } /*使用BEEP僅需要使用該函式*/ //頻率 ≈ FLSI/8/fre FLSI = 128KHz void Beep_Init(void) { CLK_ICKR |= 0x08; //開啟內部LSI while(!(CLK_ICKR&0x10)); //等待內部低速LSI就緒 BEEP_CSR = 0x20|14; //輸出1KHz 示波器測量得出 } u8 c8563_Store[4]={0x00,0x59,0x07,0x01}; /*寫入時間初值:星期一 07:59:00*/ u8 show_time[4]; void IIC_SDA_OUT(u8 x)//PB5 { PB_DDR |= 0x20; PB_CR1 |= 0x20; PB_CR2 |= 0x00; if(x == 1) PB_ODR |= 0x20; else if(x == 0)PB_ODR &= 0xDF; } void IIC_SDA_IN()//PB5 { PB_DDR &= 0xDF; PB_CR1 |= 0x20; //上拉 PB_CR2 &= 0xDF; } void IIC_SCL_OUT(u8 x)//PB4 { PB_DDR |= 0x10; PB_CR1 |= 0x10; PB_CR2 |= 0x00; if(x == 1) PB_ODR |= 0x10; else if(x == 0)PB_ODR &= 0xEF; } /**************************** I2C開始訊號 ****************************/ void Start() { IIC_SDA_OUT(1); IIC_SCL_OUT(1); Delay(); IIC_SDA_OUT(0); Delay(); IIC_SCL_OUT(0); } /**************************8 I2C結束 ****************************/ void Stop() { IIC_SDA_OUT(0); IIC_SCL_OUT(0); Delay(); IIC_SCL_OUT(1); Delay(); IIC_SDA_OUT(1); } /*********************** 輸出ACK=0 **************************/ void WriteACK() { IIC_SDA_OUT(0); Delay(); IIC_SCL_OUT(1); Delay(); IIC_SCL_OUT(0); } /************************ 輸出ACK=1 *******************/ void writenoack() { IIC_SDA_OUT(1); Delay(); IIC_SCL_OUT(1); Delay(); IIC_SCL_OUT(0); } /**************************** 等待ACK *************************/ void WaitACK() { u8 errtime=0; IIC_SDA_OUT(1); Delay(); /*讀ACK*/ IIC_SCL_OUT(1); Delay(); IIC_SDA_IN(); while(PB_IDR_IDR5) { errtime++; if(errtime==20) { break; } } IIC_SCL_OUT(0); Delay(); } /*************************** 輸出資料一位元組 ****************************/ void writebyte(u8 wdata) { u8 i; for(i=0;i<8;i++) { if(wdata&0x80) IIC_SDA_OUT(1); else IIC_SDA_OUT(0); wdata<<=1; IIC_SCL_OUT(1); Delay(); IIC_SCL_OUT(0); } WaitACK(); } /*************************** 輸入資料一位元組 **************************/ u8 Readbyte() { u8 i,bytedata; IIC_SDA_OUT(1); for(i=0;i<8;i++) { IIC_SCL_OUT(1); bytedata<<=1; IIC_SDA_IN(); bytedata|=PB_IDR_IDR5; IIC_SCL_OUT(0); Delay(); } return(bytedata); } /******************************* 輸出資料->pcf8563 ********************************/ void writeData(u8 address,u8 mdata) { Start(); writebyte(0xa2); /*寫命令*/ writebyte(address); /*寫地址*/ writebyte(mdata); /*寫資料*/ Stop(); } /*********************************** 輸入資料<-pcf8563 ***********************************/ u8 ReadData(u8 address) /*單位元組*/ { u8 rdata; Start(); writebyte(0xa2); /*寫命令*/ writebyte(address); /*寫地址*/ Start(); writebyte(0xa3); /*讀命令*/ rdata=Readbyte(); writenoack(); Stop(); return(rdata); } /******************************** 讀入時間到內部緩衝區 *********************************/ void P8563_Read() { u8 time[4]; time[0] = ReadData(0x02)&0x7f; //secod time[1] = ReadData(0x03)&0x7f;; //minute time[2] = ReadData(0x04)&0x3f;; //hour time[3] = ReadData(0x05)&0x3f;; //day show_time[0] = (time[0]/16)*10+(time[0]%16); show_time[1] = (time[1]/16)*10+(time[1]%16); show_time[2] = (time[2]/16)*10+(time[2]%16); show_time[3] = (time[3]/16)*10+(time[3]%16); } // sec min hour day // 25 13 18 11 18:13:25 u8 set_time[4]={0x25,0x13,0x18,0x11}; /******************* 寫時間修改值 *******************/ void P8563_settime() { writeData(0x02,(set_time[0])); writeData(0x03,(set_time[1])); writeData(0x04,(set_time[2])); writeData(0x05,(set_time[3])); } /**************************** P8563的初始化 ********************************/ void P8563_init() { writeData(0x00,0x20); //時鐘停止 P8563_settime(); //設定時間 writeData(0x00,0x00); //時鐘開始 } int main( void ) { System_Init(); P8563_init(); LCD5510_Init(); Timer4_init(0x07,0xc3); //12.5ms中斷一次 // Beep_Init(); delay_ms(100); while (1) { LCD_printsl(0, 0, "1233455"); LCD_printn(0,1,12345,6); P8563_Read();//讀取PCF8563時鐘資料 LCD_printn(0,2,show_time[3],2); //顯示時間 LCD_printn(3,2,show_time[2],2); LCD_printn(6,2,show_time[1],2); LCD_printn(9,2,show_time[0],2); LCD_showsh(0, 2, "永恆之心★"); } } #pragma vector=TIM4_OVR_UIF_vector __interrupt void TIM4_UPD_OVF_IRQHandler(void) { TIM4_SR=0x00; i++; if(i==50) { LCD_BL(1);//液晶背光點亮 } if(i==100) { LCD_BL(0);//液晶背光熄滅 i=0; } }