調試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液晶代碼*/
[plain] view plain copy
/*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: 待寫入的數據
//dat_cmd: 1-數據, 0-指令
void LCD_write_byte(u8 wbyte, u8 dat_cmd)
{
LCD_CE(0);//1-數據 //0-指令
LCD_DC(dat_cmd);
Spi_Send(wbyte);
LCD_CE(1);
}*/
[plain] view plain copy
/*--------------------------------------------------------------*/
//寫入一個字節(數據或指令)
//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;
}
}
上一篇:STM8S讀寫內部EEPROM
下一篇:STM8 模擬I2C驅動0.91寸OLED屏
推薦閱讀
史海拾趣
在發展過程中,如韻始終關注社會責任和可持續發展問題。公司積極參與社會公益活動,為弱勢群體提供幫助和支持。同時,如韻注重環保和節能減排工作,在產品設計和生產過程中嚴格遵守相關環保法規和標準。
為了推動行業的可持續發展,如韻還積極參與行業交流和合作活動,與同行分享經驗和資源。通過與產業鏈上下游企業的緊密合作和協同創新,如韻為推動電子行業的綠色發展和技術進步做出了積極貢獻。
1970年,Corning Cable Systems公司憑借其創新技術,成功發明了世界上首款低損耗光纖。這一里程碑式的發明徹底改變了通信行業的面貌,推動了光纖通信的飛速發展。此后,公司不斷突破技術壁壘,提升光纖性能,為全球范圍內的通信網絡建設提供了強有力的支持。
臺灣肯尼威公司成立于1986年,其創始人李明(化名)是一位對電子技術充滿熱情的工程師。在當時的臺灣,電子制造業正處于蓬勃發展的階段。李明看到電源濾波器在電子設備中的重要性,于是決定專注于這一領域的研發和生產。他帶領一支小團隊,經過無數次的試驗和改進,終于成功研發出CW系列單相電源濾波器,為公司的發展奠定了堅實的技術基礎。
進入21世紀后,E-T-A公司開始關注智能電路保護技術的研發。公司投入大量資源進行技術創新,成功推出了多款智能電路保護產品。這些產品不僅具有更高的安全性和可靠性,還能實現遠程監控和控制功能,為客戶提供更加便捷和高效的服務。
面對數字化浪潮的沖擊,ECC決定進行數字化轉型以提升競爭力。公司引入了先進的生產設備和管理系統,實現了生產過程的自動化和智能化。同時,ECC還建立了大數據分析平臺,對市場需求、客戶需求等數據進行深入分析,為公司的決策提供有力支持。數字化轉型使得ECC在市場競爭中更加靈活和高效。
Aeroflex 5800系列設備滿足不斷發展的自動測試需求 如果您是一位工程師,而且正在進行混合信號測試、器件編程、功能測試、在系統編程或者簡單協議通信,那么Aeroflex設計的5800系列自動測試設備(ATE系統)能夠讓您的工作更輕松。5800系列ATE設備采用開放式并且高度可配置的結構,因而能輕松適應不斷發 ...… 查看全部問答∨ |
|
下面是本人下載的的RV MDK微控制器開發平臺的視頻講解 。。 里面對國內國際所使用的RV MDK開發工具做出了詳細的指導,給出了他們個人的見解。 對于學習CORTEX M3和ARM技術有相當好的幫助。。。 用MDK ...… 查看全部問答∨ |
STM 32 103xx 用SPI2作為Slave,和inter 196KC通訊時收不到數據,196端用IO口模擬SPI時序,用示波器觀看和SPI2連接的MOSI和SCK 均有波形.估計196KC的程序沒有錯誤的,因為和196端還同時連接一個X25045 ...… 查看全部問答∨ |
各位好, 我把STM32 用串口ISP燒寫了 IAP (DfuSe需要與之通訊),并且對STM32 作了讀保護。 然后用 DfuSe 軟件 更新了我的用戶程序(APP)。 是可以讀保護了,因為 用Jlink 的 JTAG口 是讀不出來, ...… 查看全部問答∨ |