一、HT1621電路分析數組
HT1621爲32×4即128點內存映像LCD驅動器,包含內嵌的32×4位顯示RAM內存和時基發生器以及WDT看門狗定時器.ide
HT1621驅動電路以下圖所示:函數
圖1spa
與單片機相鏈接控制的有9腳CS,3腳WR,12腳DATA,其功能描述以下表。3d
圖2code
二、字符顯示原理orm
液晶管點亮和熄滅原理分別爲在對應的RAM地址中寫1和寫0.首先須要清楚所驅動控制的液晶的COM-SEG對應關係,而後須要瞭解HT1621的32×4RAM地址映射。對象
例如要控制的液晶的裝腳成品圖部分以下:blog
圖3ip
着重看一個液晶數碼管,咱們瞭解原理就行。能夠看到圖3中是第2個液晶數碼管,有7段,分別爲A,B,C,D,E,F,G。也就分別爲下面COM\SEG地址對應關係圖中的2A,2B,2C,2D,2E,2F,2G。
液晶的顯示字符的部分COM公共端輸出口和SEG段輸出口的分佈以下表所示,同理咱們能夠看到例如:2D對應(SEG5,COM0),2E對應(SEG5,COM1),2F對應(SEG5,COM2),2A對應(SEG5,COM3),2C對應(SEG4,COM1),2G對應(SEG4,COM2),2B對應(SEG4,COM3)。
圖4
搞清楚咱們要控制的對象以後那, HT1621的RAM 地址映射以下圖所示:
圖5
能夠清楚的看到要控制液晶段對應SEG號做爲6位地址,COM號對應做爲4位數據寫入,此時注意4位數據的高低位。寫數據到RAM命令格式爲:101+6位RAM地址+4位數據,其中RAM地址爲SEG序號.
例如咱們在圖3的第二個液晶數碼管上顯示數字,首先咱們根據圖3獲得地址映射關係,先寫入地址SEG4中的四位數據(COM3,COM2,COM1,COM0),再寫如地址SEG5中的四位數據(COM3,COM2,COM1,COM0),對應關係以下:
SEG4 |
SEG5 |
||||||
COM3 |
COM2 |
COM1 |
COM0 |
COM3 |
COM2 |
COM1 |
COM0 |
2B |
2G |
2C |
T10 |
2A |
2F |
2E |
2D |
因此若是在圖3中顯示「5」,則在顯示的液晶段對應地址上寫1,不顯示寫0,以下圖所示。因此SEG4地址應寫入的數據爲0110 ,SEG5地址應寫入數據1101。
圖6
三、顯示的保持
寫數據過程須要保證寫前無關位數據的保持,所以在單片機程序中開闢32×4數組做爲虛擬ARM,存儲寫前LCD顯示數據.經過與清零,或置位操做實現,例如6位地址Address當前顯示的數據爲Data_last .若Xi(i=0,1,2,3) 位須要保持,則Xi爲1,不然Xi爲0.寫入的數據爲Data_now,變換公式爲:
四、程序
主要的程序編寫流程以下:
圖7
程序的參考步驟:①Display_Wendu_1②write_addr_dat_n_wendu③write_mode④write_address⑤write_data_4bit,其中Lcdram數組爲創建的虛擬數組。
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
1 unsigned char Lcdram[32]= 2 { 3 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 4 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 7 }; 8 9 const unsigned char Wendu[] = //溫度0-9 10 { 11 0X5F, 0X50, 0X3D, 0X79, 0X72, 0X6B, 0X6F, 0X51, 0X7F, 0X7B 12 }; 13 ///////////////////////////////////////////////////驅動函數 14 /* 15 * LCD 模式寫入 16 * 入口:MODE :COM(命令模式) DAT(數據模式) 17 * 出口:void 18 */ 19 void write_mode(unsigned char MODE) //寫入模式,數據or命令 20 { 21 GPIO_ResetBits(GPIOB, HT1621_WR); // RW = 0; 22 delay_us(10); 23 GPIO_SetBits(GPIOB, HT1621_DATA); // DA = 1; 24 GPIO_SetBits(GPIOB, HT1621_WR); // RW = 1; 25 delay_us(10); 26 27 GPIO_ResetBits(GPIOB, HT1621_WR); // RW = 0; 28 delay_us(10); 29 GPIO_ResetBits(GPIOB, HT1621_DATA); // DA = 0; 30 GPIO_SetBits(GPIOB, HT1621_WR); // RW = 1; 31 delay_us(10); 32 33 GPIO_ResetBits(GPIOB, HT1621_WR); // RW = 0; 34 delay_us(10); 35 36 if (0 == MODE) 37 { 38 GPIO_ResetBits(GPIOB, HT1621_DATA); // DA = 0; 39 } 40 else 41 { 42 GPIO_SetBits(GPIOB, HT1621_DATA); // DA = 1; 43 } 44 delay_us(10); 45 GPIO_SetBits(GPIOB, HT1621_WR); // RW = 1; 46 delay_us(10); 47 } 48 49 /* 50 * LCD 命令寫入函數 51 * 入口:cbyte ,控制命令字 52 * 出口:void 53 */ 54 void write_command(unsigned char Cbyte) 55 { 56 unsigned char i = 0; 57 58 for (i = 0; i < 8; i++) 59 { 60 GPIO_ResetBits(GPIOB, HT1621_WR); 61 if ((Cbyte >> (7 - i)) & 0x01) 62 { 63 GPIO_SetBits(GPIOB, HT1621_DATA); 64 } 65 else 66 { 67 GPIO_ResetBits(GPIOB, HT1621_DATA); 68 } 69 delay_us(10); 70 GPIO_SetBits(GPIOB, HT1621_WR); 71 delay_us(10); 72 } 73 GPIO_ResetBits(GPIOB, HT1621_WR); 74 delay_us(10); 75 GPIO_ResetBits(GPIOB, HT1621_DATA); 76 GPIO_SetBits(GPIOB, HT1621_WR); 77 delay_us(10); 78 } 79 80 /* 81 * LCD 地址寫入函數 82 * 入口:cbyte,地址 83 * 出口:void 84 */ 85 void write_address(unsigned char Abyte) 86 { 87 unsigned char i = 0; 88 Abyte = Abyte << 2; 89 90 for (i = 0; i < 6; i++) 91 { 92 GPIO_ResetBits(GPIOB, HT1621_WR); 93 //delay_us(10); 94 if ((Abyte >> (7 - i)) & 0x01) 95 { 96 GPIO_SetBits(GPIOB, HT1621_DATA); 97 } 98 else 99 { 100 GPIO_ResetBits(GPIOB, HT1621_DATA); 101 } 102 delay_us(10); 103 GPIO_SetBits(GPIOB, HT1621_WR); 104 delay_us(10); 105 } 106 107 } 108 109 /* 110 * LCD 數據寫入函數 111 * 入口:Dbyte,數據 112 * 出口:void 113 */ 114 void write_data_8bit(unsigned char Dbyte) 115 { 116 int i = 0; 117 118 for (i = 0; i < 8; i++) 119 { 120 GPIO_ResetBits(GPIOB, HT1621_WR); 121 delay_us(10); 122 if ((Dbyte >> (7 - i)) & 0x01) 123 { 124 GPIO_SetBits(GPIOB, HT1621_DATA); 125 } 126 else 127 { 128 GPIO_ResetBits(GPIOB, HT1621_DATA); 129 } 130 delay_us(10); 131 GPIO_SetBits(GPIOB, HT1621_WR); 132 delay_us(10); 133 } 134 } 135 136 void write_data_4bit(unsigned char Dbyte) 137 { 138 int i = 0; 139 140 for (i = 0; i < 4; i++) 141 { 142 GPIO_ResetBits(GPIOB, HT1621_WR); 143 //delay_us(10); 144 if ((Dbyte >> (3 - i)) & 0x01) 145 { 146 GPIO_SetBits(GPIOB, HT1621_DATA); 147 } 148 else 149 { 150 GPIO_ResetBits(GPIOB, HT1621_DATA); 151 } 152 delay_us(10); 153 GPIO_SetBits(GPIOB, HT1621_WR); 154 delay_us(10); 155 } 156 } 157 158 159 160 //1621初始化 161 void ht1621_init(void) 162 { 163 GPIO_InitTypeDef GPIO_InitStructure;// declare the structure 164 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); 165 166 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE); 167 memset(&GPIO_InitStructure, 0, sizeof(GPIO_InitTypeDef)); 168 GPIO_InitStructure.GPIO_Pin = HT1621_WR | HT1621_DATA ;//| HT1621_IRQ 169 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 170 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 171 GPIO_Init(GPIOB, &GPIO_InitStructure); 172 173 memset(&GPIO_InitStructure, 0, sizeof(GPIO_InitTypeDef)); 174 GPIO_InitStructure.GPIO_Pin = HT1621_CS ;//| HT1621_IRQ 175 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 176 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 177 GPIO_Init(GPIOA, &GPIO_InitStructure); 178 179 } 180 181 /* 182 * LCD 初始化,對lcd自身作初始化設置 183 * 入口:void 184 * 出口:void 185 */ 186 void lcd_init(void) 187 { 188 ////////////////////////////////////////////////////// 189 GPIO_SetBits(GPIOA, HT1621_CS); 190 GPIO_SetBits(GPIOB, HT1621_WR); 191 GPIO_SetBits(GPIOB, HT1621_DATA); 192 for (ii=0;ii<10000;ii++) 193 {for(j=10;j>0;j--);} 194 ////////////////////////////////////////////////////// 195 GPIO_ResetBits(GPIOA, HT1621_CS); //CS = 0; 196 //delay_us(10); 197 for (ii=0;ii<10000;ii++) 198 {for(j=10;j>0;j--);} 199 write_mode(COMMAND); //命令模式 200 write_command(0x01); //Enable System 201 write_command(0x03); //Enable Bias 202 write_command(0x04); //Disable Timer 203 write_command(0x05); //Disable WDT 204 write_command(0x08); //Tone OFF 205 write_command(0x18); //on-chip RC震盪 206 write_command(0x29); //1/4Duty 1/3Bias 207 write_command(0x80); //Disable IRQ 208 write_command(0x40); //Tone Frequency 4kHZ 209 write_command(0xE3); //Normal Mode 210 211 GPIO_SetBits(GPIOA, HT1621_CS); //CS = 1; 212 } 213 214 /* 215 * LCD 清屏函數 216 * 入口:void 217 * 出口:void 218 */ 219 void lcd_clr(void) 220 { 221 write_addr_dat_n(0x0, 0x00, 32);//15 222 } 223 //用於溫度區域寫數據 224 void write_addr_dat_n_wendu(unsigned char _addr, unsigned char _dat, unsigned char n) 225 { 226 227 unsigned char i = 0; 228 unsigned char _dat_temp1,_dat_temp2; 229 230 //WriteLcdram(_addr, _dat); 231 232 233 234 GPIO_ResetBits(GPIOA, HT1621_CS); // CS = 0; 235 write_mode(DAT); 236 237 if(Lcdram[_addr]==0x00) 238 { 239 WriteLcdram(_addr, _dat); 240 } 241 if((_addr%2)==0) 242 { 243 _dat_temp1=Lcdram[_addr]; 244 _dat_temp2=(_dat_temp1&0x08)|_dat; 245 246 write_address(_addr); 247 for (i = 0; i < n; i++) 248 { 249 write_data_4bit(_dat_temp2); 250 } 251 GPIO_SetBits(GPIOA, HT1621_CS); //CS = 1; 252 253 } 254 else if((_addr%2)!=0) 255 { 256 write_address(_addr); 257 for (i = 0; i < n; i++) 258 { 259 write_data_4bit(_dat); 260 } 261 GPIO_SetBits(GPIOA, HT1621_CS); 262 } 263 264 WriteLcdram(_addr, _dat_temp2); 265 } 266 267 //用於溼度區域寫數據 268 void write_addr_dat_n_shidu(unsigned char _addr, unsigned char _dat, unsigned char n) 269 { 270 271 unsigned char i = 0; 272 unsigned char _dat_temp1,_dat_temp2; 273 274 //WriteLcdram(_addr, _dat); 275 276 277 278 GPIO_ResetBits(GPIOA, HT1621_CS); // CS = 0; 279 write_mode(DAT); 280 281 if(Lcdram[_addr]==0x00) 282 { 283 WriteLcdram(_addr, _dat); 284 } 285 if((_addr%2)==0) 286 { 287 _dat_temp1=Lcdram[_addr]; 288 _dat_temp2=(_dat_temp1&0x01)|_dat; 289 290 write_address(_addr); 291 for (i = 0; i < n; i++) 292 { 293 write_data_4bit(_dat_temp2); 294 } 295 GPIO_SetBits(GPIOA, HT1621_CS); //CS = 1; 296 297 } 298 else if((_addr%2)!=0) 299 { 300 write_address(_addr); 301 for (i = 0; i < n; i++) 302 { 303 write_data_4bit(_dat); 304 } 305 GPIO_SetBits(GPIOA, HT1621_CS); 306 } 307 308 WriteLcdram(_addr, _dat_temp2); 309 } 310 311 312 //用於底部數字寫數據 313 void write_addr_dat_n_others(unsigned char _addr, unsigned char _dat, unsigned char n) 314 { 315 316 unsigned char i = 0; 317 unsigned char _dat_temp1,_dat_temp2; 318 GPIO_ResetBits(GPIOA, HT1621_CS); // CS = 0; 319 write_mode(DAT); 320 321 if(Lcdram[_addr]==0x00) 322 { 323 WriteLcdram(_addr, _dat); 324 325 } 326 if((_addr%2)==0) 327 { 328 _dat_temp1=Lcdram[_addr]; 329 _dat_temp2=(_dat_temp1&0x01)|_dat; 330 331 write_address(_addr); 332 for (i = 0; i < n; i++) 333 { 334 write_data_4bit(_dat_temp2); 335 } 336 GPIO_SetBits(GPIOA, HT1621_CS); //CS = 1; 337 338 } 339 else if((_addr%2)!=0) 340 { 341 write_address(_addr); 342 for (i = 0; i < n; i++) 343 { 344 write_data_4bit(_dat); 345 } 346 GPIO_SetBits(GPIOA, HT1621_CS); 347 } 348 349 //WriteLcdram(_addr, _dat); 350 WriteLcdram(_addr, _dat_temp2); 351 } 352 353 //用於字符寫數據 354 void write_addr_dat_n_char(unsigned char _addr, unsigned char _dat, unsigned char state) 355 { 356 357 unsigned char i = 0; 358 unsigned char _dat_temp1,_dat_temp2; 359 360 361 GPIO_ResetBits(GPIOA, HT1621_CS); // CS = 0; 362 write_mode(DAT); 363 364 _dat_temp1=Lcdram[_addr]; 365 if(state==1) 366 { 367 368 _dat_temp2=(_dat_temp1|_dat); 369 } 370 else if(state==0) 371 { 372 _dat_temp2=(_dat_temp1&(~_dat)); 373 } 374 write_address(_addr); 375 376 for (i = 0; i < 1; i++) 377 { 378 write_data_4bit(_dat_temp2); 379 } 380 GPIO_SetBits(GPIOA, HT1621_CS); //CS = 1; 381 WriteLcdram(_addr, _dat_temp2); 382 383 384 385 386 } 387 //顯示溫度 388 //入口:pos,顯示位置,地址0、二、4分別爲從右到左的三個數字 389 // num:要顯示的一位數 390 void Display_Wendu_1(unsigned char add, unsigned char num ) 391 { 392 unsigned char n,i,j; 393 n=getChr_Wendu(num); 394 i=(n&0xF0)>>4; 395 j=n&0x0F; 396 write_addr_dat_n_wendu(add,i,1); 397 write_addr_dat_n_wendu(add+1,j,1); 398 399 } 400 401 402 //溫度數據轉換,lcd.c內部使用 403 unsigned char getChr_Wendu(unsigned char c) 404 { 405 unsigned char i; 406 for ( i = 0; i < 10; ++i) 407 { 408 if (c == i) 409 { 410 return Wendu[i]; 411 } 412 } 413 } 414 415 //更新lcdram數組 416 void WriteLcdram(unsigned char add, unsigned char data) 417 { 418 419 Lcdram[add]=data; 420 421 }
當軒不是憐蒼翠,只要人知耐歲寒。
轉載需說明出處,筆者總結以前的知識,與你們分享,有問題的能夠留給我哦~