|  | 
          11樓
          巨大八爪鱼
          2017-4-4 16:06
          
          
            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有下划线警告的问题。
 
 | 
    
      |  | 
          12樓
          巨大八爪鱼
          2017-4-4 16:13
          
          
            另外,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 ==========
 
 | 
    
      |  | 
          15樓
          巨大八爪鱼
          2017-4-4 18:01
          
          
            【更新后的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;
 }
 
 |