 |
5V電源上程序卡死的問題已經解決了。是因為開機時的滿屏顯示電流過大導致的。 (當電源電壓=5.76V時滿屏顯示需要非常大的電流,單片機承受不了) 把滿屏顯示的程序改成一行一行地動態掃描就解決問題了。
【更新後的matrixFull函數】 void matrixFull(void) { uint8_t i, tmp; uint32_t cnt = 100; while (cnt--) { tmp = 1; for (i = 0; i < 8; i++) { HC595_SerIn(~tmp); // 寫成~_BV(i)太占空間, 改成這種形式會節約一點空間 HC595_SerIn(0x00); HC595_ParOut(); _delay_ms(1); tmp <<= 1; } } }
由於晶片所剩的Flash空間已經不多了,而_BV裡面的(1<<n)語句和~運算符要占用好幾十字節的Flash,所以設置了一個tmp變量來代替。 在Windows下的Atmel Studio裡面編譯時,可添加一個頭文件:#include <avr/sfr_defs.h>,以解決代碼編輯器里_BV有下劃線警告的問題。
|
 |
另外,matrixScan函數裡有幾個HC595_ParOut是多餘的,應該去掉。 編譯後,占用的Flash大小為1018位元組(容量為1024位元組)。 EEPROM是之前燒寫好了的,用完了整個64位元組的空間。 【編譯信息】 ------ Build started: Project: TinyBoard, Configuration: Debug AVR ------ Build started. Project "TinyBoard.cproj" (default targets): Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!=''). Target "CoreBuild" in file "C:\Program Files (x86)\Atmel\Studio\7.0\Vs\Compiler.targets" from project "E:\Users\Octopus\Documents\Atmel Studio\7.0\TinyBoard\TinyBoard\TinyBoard.cproj" (target "Build" depends on it): Task "RunCompilerTask" Shell Utils Path C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils\make.exe all --jobs 4 --output-sync make: Nothing to be done for 'all'. Done executing task "RunCompilerTask". Task "RunOutputFileVerifyTask" Program Memory Usage : 1018 bytes 99.4 % Full Data Memory Usage : 8 bytes 12.5 % Full Done executing task "RunOutputFileVerifyTask". Done building target "CoreBuild" in project "TinyBoard.cproj". Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)' != '') was evaluated as ('' != ''). Target "Build" in file "C:\Program Files (x86)\Atmel\Studio\7.0\Vs\Avr.common.targets" from project "E:\Users\Octopus\Documents\Atmel Studio\7.0\TinyBoard\TinyBoard\TinyBoard.cproj" (entry point): Done building target "Build" in project "TinyBoard.cproj". Done building project "TinyBoard.cproj".
Build succeeded. ========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
|
 |
【更新後的main.c文件】 #include <avr/io.h> #include <avr/eeprom.h> #include <avr/pgmspace.h> #include <avr/sfr_defs.h> #define F_CPU 1200000U #include <util/delay.h> #include "74HC595.h"
#define K1 (PINB&_BV(3))
const uint8_t* EEPROM_START = 0x00; unsigned char count = 0; unsigned char num = 0x0; unsigned char left = 252; unsigned char right = 0;
unsigned char status = 0x00; #define ROLL 7 #define PAUSE 5
const unsigned char NUM0TO7[] PROGMEM = { 0x0C, 0x12, 0x12, 0x12, 0x12, 0x12, 0x0C, 0x00, 0x08, 0x0C, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x0C, 0x12, 0x10, 0x08, 0x04, 0x02, 0x1E, 0x00, 0x0C, 0x12, 0x10, 0x0C, 0x10, 0x12, 0x0C, 0x00, 0x08, 0x0C, 0x0C, 0x0A, 0x0A, 0x1E, 0x08, 0x00, 0x1E, 0x02, 0x02, 0x0E, 0x10, 0x10, 0x0E, 0x00, 0x0C, 0x12, 0x02, 0x0E, 0x12, 0x12, 0x0C, 0x00, 0x1E, 0x12, 0x10, 0x08, 0x04, 0x04, 0x04, 0x00};
unsigned char read(unsigned char pos) { if (pos < 64) return pgm_read_byte(NUM0TO7 + pos); else { pos -= 64; eeprom_busy_wait(); return eeprom_read_byte(EEPROM_START + pos); } }
void matrixFull(void) { uint8_t i, tmp; uint32_t cnt = 100; while (cnt--) { tmp = 1; for (i = 0; i < 8; i++) { HC595_SerIn(~tmp); // 寫成~_BV(i)太占空間, 改成這種形式會節約一點空間 HC595_SerIn(0x00); HC595_ParOut(); _delay_ms(1); tmp <<= 1; } } }
void matrixScan(unsigned char times) { unsigned char i; while (times--) { if (status & _BV(ROLL)) { /* Roll numbers 0x0 ~ 0xF */ for (i = 0; i < 8; i++) { HC595_SerIn(~_BV(i)); if (i < 7) { if (left > 200) { /* -1 => 255 (<<4), 4 = 3 + (56 - ([255] - 200)) ** -2 => 254 (<<5), 5 = 3 + (56 - ([254] - 200)) ** -3 => 253 (<<6), 6 = 3 + (56 - ([253] - 200)) ** -4 => 252 (<<7), 7 = 3 + (56 - ([252] - 200)) : completely hidden **/ right = (read(num * 8 + i) << (3 + (56 - (left - 200)))); } else right = ((read(num * 8 + i) << 3) >> left); } else { /* The dot at the bottom */ if (num == 0x0 && (left == 0 || left > 200)) { // Do not display ". 0" right = 0x00; } else if (num == 0xf && (left >= 3 && left < 200)) { // Do not display "F ." right = 0x00; } else { if (left < 200 && left >= 5) right = (0x80 >> (left - 5)); else if (left > 200) { /* -4 => 252 (>>3), 3 = [252] - 249 ** -3 => 253 (>>4), 4 = [253] - 249 ** -2 => 254 (>>5), 5 = [254] - 249 ** -1 => 255 (>>6), 6 = [255] - 249 **/ right = (0x80 >> (left - 249)); } else if (left == 0) right = 0x01; else right = 0x00; } } HC595_SerIn(~right); HC595_ParOut(); _delay_us(500); } if (!(status & _BV(PAUSE))) { count++; if (count >= 10) { count = 0; left++; if (left < 200 && left >= 8) { // display the next number left = 252; num++; if (num >= 0x10) { // when all the 16 numbers have appeared num = 0x00; status &= ~_BV(ROLL); // stop rolling numbers } } } } } else { /* Display Numbers 0x00 ~ 0xFF */ for (i = 0; i < 8; i++) { HC595_SerIn(~_BV(i)); left = (read((num / 0x10) * 8 + i) >> 1); right = (read((num % 0x10) * 8 + i) << 3); HC595_SerIn(~(left | right)); HC595_ParOut(); _delay_us(500); } if (!(status & _BV(PAUSE))) { count++; if (count >= 80) { count = 0; num++; // num is from 0x00 to 0x99; it's impossible to be 0x100 if (num == 0x00) { status |= _BV(ROLL); // begin to roll numbers num = 0x0; left = 252; } } } } } }
void keyScan(void) { // PAUSE Key if (!K1) { matrixScan(7); if (!K1) { if (status & _BV(PAUSE)) { PORTB |= _BV(4); status &= ~_BV(PAUSE); } else { PORTB &= ~_BV(4); status |= _BV(PAUSE); } while (K1) matrixScan(5); matrixScan(14); } } }
int main(void) { DDRB = 0x17; // 00010111 PORTB = 0x1f; // 00011111 matrixFull(); status |= _BV(ROLL); while (1) { matrixScan(1); keyScan(); } return 0; }
|