Arduino : PROGMEM 2D Array
PROGMEM을 사용하여 2차원 배열을 FLASH MEMORY 에 사용하는 법
에 대해 소개합니다.문자열 배열에서 사용하기
아두이노에서 많은 양의 텍스트를 작업할 때 문자열을 배열로 설정하여 편리하게 사용할 수 있습니다. 문자열은 기본적으로 char* 의 배열이기 때문에, 여러 문자열을 배열로 저장하는 것은 사실상 2차원 배열입니다.
코드
아래 코드는 아두이노 공식 사이트에서의 예제 코드를 약간 수정하였습니다. 수정한 내용은 주석을 삭제하고, 20번 Line 에서 string_table 배열에서 buffer 로 저장되는 코드를 수정하였습니다. 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | const char string_0[] PROGMEM = "String 0"; const char string_1[] PROGMEM = "String 1"; const char string_2[] PROGMEM = "String 2"; const char string_3[] PROGMEM = "String 3"; const char string_4[] PROGMEM = "String 4"; const char string_5[] PROGMEM = "String 5"; const char *const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5}; char buffer[30]; void setup() { Serial.begin(9600); delay(2000); Serial.println("OK"); } void loop() { for (int i = 0; i < 6; i++) { strcpy_P(buffer, pgm_read_byte_near(&(string_table[i]))); Serial.println(buffer); delay(500); } } | cs |
코드 설명
- 1~5번 라인은 출력할 문자열들을 저장하는 배열을 Flash Memory 에 저장하는 코드입니다.
- 8 Line : 1~5 Line 에서 설정한 문자열을 배열로 감싸는 코드입니다. 문자열 자체가 배열이기 떄문에 string_table 은 2차원 배열이 됩니다.
- 10 Line :
buffer는 출력할 메세지를 임시로 저장하는 버퍼로, 프로그램 실행시 SRAM 에 업로드 되어 사용됩니다. - 20 Line : string_table 메세지 테이블에서 buffer 로 데이터를 저장하는 코드 입니다. 기존 아두이노 사이트의 예제에서는 아래와 같은 코드를 사용했지만,
pgm_read_word는 지난 포스트의 16bit 데이터를 읽어 들이는pgm_read_word_near과 동일하고 최종적으로(char *)로 캐스트하기 때문에pgm_read_byte_near로 사용해도 무방하다고 판단했습니다. 아두이노 에서 제공하는 예제대로 하셔도 무방합니다.
아두이노 예제 코드 : strcpy_P(buffer, (char *)pgm_read_word(&(string_table[i])));
※ 주의사항 : 위 코드와 같이 문자열을 테이블로 감싸는 배열은 const char *const 로 선언 되어야 합니다. const char *const 가 무슨 의미인지 알기 위해 몇시간을 알아보았으나 정확히 모르겠습니다. 아시는 분은 공유해주시면 감사하겠습니다. 2차원 배열을 만드는 방법도 위의 코드방식을 따라야 합니다. 아래와 같이 코드를 작성하는 경우 빌드는 되지만 정상 동작 하지 않습니다.
const char *const string_table[] PROGMEM = { "string_0" , "string_1", "string_2", "string_3", "string_4", "string_5"};
실행 결과
아래와 같이 String 0 ~ String 5 의 메세지가 순차적으로 표시되는 것을 볼 수 있습니다.
LED Matrix 코드에 적용하기
하단에 링크된 LED Matrix 코드에서 문제점은 프로그램 빌드시 SRAM 메모리가 70% 차지하여, 안정성에 문제가 생길 수 있습니다. SRAM 은 프로그램이 동작하면서 사용 메모리는 프로그램에 따라 변하기 떄문에, 메모리 부족으로 예상치 못하는 문제가 항상 발생 할 수 있습니다. 이를 해결하기 위해 본 포스트에서 소개한 PROGMEM 을 적용하여 코드를 작성하였습니다.
코드
수정된 코드를 일부만 넣을지, 고민을 하다가 전체 코드를 넣기로 했습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | #define BUADRATE 115200 #define BUFFERSIZE 40 #define SCROLLTIME 50 // Coloumn Pin 할당 #define C1 9 #define C2 12 #define C3 7 #define C4 13 #define C5 A2 #define C6 6 #define C7 3 #define C8 A5 // Row Pin 할당 #define R1 2 #define R2 11 #define R3 10 #define R4 A4 #define R5 8 #define R6 A3 #define R7 4 #define R8 5 // Bit 추출 메크로 : data 에서 loc 번째 비트 부터 area 영역 만큼 추출 // ex) extract_bits( 0b00000010, 1, 2) 결과 1 -> 0b00000010 데이터의 2번째 비트 1크기 만큼 추출 #define extract_bits(data, area, loc) (((data) >> (loc)) & (area)) int colPin[8] = {C1, C2, C3, C4, C5, C6, C7, C8}; int rowPin[8] = {R1, R2, R3, R4, R5, R6, R7, R8}; const byte font[128][8] PROGMEM = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0000 (nul) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0001 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0002 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0003 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0004 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0005 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0006 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0007 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0008 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0009 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000A { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000B { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000C { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000D { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000E { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000F { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0010 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0011 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0012 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0013 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0014 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0015 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0016 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0017 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0018 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0019 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001A { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001B { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001C { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001D { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001E { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001F { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 (space) { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, // U+0021 (!) { 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0022 (") { 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // U+0023 (#) { 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // U+0024 ($) { 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // U+0025 (%) { 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // U+0026 (&) { 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0027 (') { 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // U+0028 (() { 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // U+0029 ()) { 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // U+002A (*) { 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // U+002B (+) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+002C (,) { 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // U+002D (-) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+002E (.) { 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // U+002F (/) { 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00}, // U+0030 (0) { 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // U+0031 (1) { 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // U+0032 (2) { 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // U+0033 (3) { 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00}, // U+0034 (4) { 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // U+0035 (5) { 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // U+0036 (6) { 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00}, // U+0037 (7) { 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+0038 (8) { 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // U+0039 (9) { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+003A (:) { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+003B (//) { 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // U+003C (<) { 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00}, // U+003D (=) { 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // U+003E (>) { 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00}, // U+003F (?) { 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00}, // U+0040 (@) { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0041 (A) { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0042 (B) { 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // U+0043 (C) { 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00}, // U+0044 (D) { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0045 (E) { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // U+0046 (F) { 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // U+0047 (G) { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0048 (H) { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0049 (I) { 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // U+004A (J) { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+004B (K) { 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // U+004C (L) { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+004D (M) { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+004E (N) { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+004F (O) { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+0050 (P) { 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // U+0051 (Q) { 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00}, // U+0052 (R) { 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00}, // U+0053 (S) { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0054 (T) { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // U+0055 (U) { 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0056 (V) { 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // U+0057 (W) { 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+0058 (X) { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+0059 (Y) { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+005A (Z) { 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00}, // U+005B ([) { 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00}, // U+005C (\) { 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+005D (]) { 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00}, // U+005E (^) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+005F (_) { 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0060 (`) { 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // U+0061 (a) { 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00}, // U+0062 (b) { 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // U+0063 (c) { 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00}, // U+0064 (d) { 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00}, // U+0065 (e) { 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00}, // U+0066 (f) { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0067 (g) { 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00}, // U+0068 (h) { 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0069 (i) { 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E}, // U+006A (j) { 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00}, // U+006B (k) { 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+006C (l) { 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00}, // U+006D (m) { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00}, // U+006E (n) { 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+006F (o) { 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+0070 (p) { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78}, // U+0071 (q) { 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00}, // U+0072 (r) { 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00}, // U+0073 (s) { 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0074 (t) { 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00}, // U+0075 (u) { 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0076 (v) { 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00}, // U+0077 (w) { 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // U+0078 (x) { 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0079 (y) { 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00}, // U+007A (z) { 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00}, // U+007B ({) { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+007C (|) { 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00}, // U+007D (}) { 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E (~) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // U+007F }; byte displayData[8]; // 최종 8x8 출력 할 데이터 byte stringBuffer[BUFFERSIZE][8]; // 스크롤 할 데이터를 저장할 버퍼 int iTextLenth; int scrollTime = SCROLLTIME; // scrollTime 만큼 한 글자씩 시프트 String myString; bool recFlag = false; // 시리얼로 문자열 입력 받은 경우 활성화 되는 Flag bool changeFlag = false; // LED Matrix 에 출력할 데이터가 변경되어야 하는 경우 활성화 되는 Flag void setup() { String initialString = "INPUT STRING"; iTextLenth = initialString.length(); for(int i = 0 ; i < 8 ; i++) { pinMode(colPin[i], OUTPUT); digitalWrite(colPin[i], LOW); // Column 핀은 LOW 로 초기화 pinMode(rowPin[i], OUTPUT); digitalWrite(rowPin[i], HIGH); // Row 핀은 HIGH 로 초기화 } for(int i = 1 ; i < iTextLenth+1 ; i++){ for(int j = 0 ; j < 8 ; j++){ stringBuffer[i][j] = pgm_read_byte(&(font[initialString.charAt(i-1)][j])); } } Serial.begin(BUADRATE); while(!Serial) { ; } Serial.println(F("8x8 LED Dot Matrix Program Start..")); delay(500); Serial.print(F("Input String >> ")); } void loop() { /* 시리얼 통신으로 문자열을 입력 받은 경우 실행되는 if문 */ if(recFlag == true) { recFlag = false; iTextLenth = myString.length(); for(int i = 0 ; i < BUFFERSIZE ; i++){ for(int j = 0; j < 8; j++){ stringBuffer[i][j] = 0; } } for(int i = 1 ; i < iTextLenth+1 ; i++){ for(int j = 0 ; j < 8 ; j++){ stringBuffer[i][j] = pgm_read_byte(&(font[myString.charAt(i-1)][j])); } } Serial.println(F("String Output Completed!")); Serial.print(F("Input String >> ")); myString = ""; changeFlag = true; } unsigned long now = millis(); static unsigned long pastTime; /* scrollTime 시간 마다 실행되는 if문 scrollTime 마다 최종 출력 데이터 displayData 를 한칸씩 시프트합니다. */ if(now - pastTime >= scrollTime){ pastTime = now; static int count; static int index; if(changeFlag == 1){ changeFlag = 0; count = 0; index = 0; } for(int i = 0 ; i < 8 ; i++){ displayData[i] = (stringBuffer[index][i] >> count) | (stringBuffer[index+1][i] << 8 - count); } count++; if(count == 8) { count = 0; index++; if(index == iTextLenth + 1) index = 0; } } for(int i = 0 ; i < 8 ; i++) { for(int j = 0 ; j < 8 ; j++) { digitalWrite(colPin[j], extract_bits(displayData[i],0x01,j)); // Coloumn 핀에 데이터 쓰기 } digitalWrite(rowPin[i], LOW); // i 행 활성화 delayMicroseconds(100); digitalWrite(rowPin[i], HIGH); // i 행 비활성화 } } void serialEvent() // 엔터가 입력되기 까지의 문자를 myString 에 저장하고 recFlag 를 초기화 { char myChar = (char)Serial.read(); myString += myChar; if(myChar == '\n') { recFlag = true; } } | cs |
코드 설명
- 31 Line : Font Data 를 Flash Memory 로 저장하는 코드 입니다.
- 188, 219 Line : Flash 메모리에 저장된 Font 데이터를 LED Matrix 출력버퍼에 저장하는 코드 입니다.
- 기타 :
Serial.print와 같은 시리얼 출력 코드에 사용되는 문자열은F()메크로를 적용하였습니다.
결과 비교
프로그램 실행시 동작은 동일하기 때문에 생략하고, 메모리 사용율 결과만 안내드립니다. 기존 코드를 사용시 SRAM 사용율이 70% 로 여유 공간이 없었으나, PROGMEM 와 F() 메크로 사용시 28% 로 사용 공간이 줄어 들었습니다. SRAM 사용 공간이 줄어든 만큼 다른 장치 제어 또는 코드 작성이 가능해집니다.
PROGMEM 매트로 사용시 메모리 변화
마무리
2차원 배열을 PROGMEM 매크로로 FLASH에 저장하는 방법을 소개하고, 지난 포스트의 LED Matrix 코드에 적용하여 SRAM 사용율이 줄어드는 것을 확인
하였습니다.끝까지 읽어 주셔서 감사합니다.😊
- https://www.arduino.cc/reference/en/language/variables/utilities/progmem/ [본문으로]
'Embedded > Arduino' 카테고리의 다른 글
아두이노 강좌 #30 Servo 라이브러리 기본 사용법 (9) | 2020.08.29 |
---|---|
아두이노 강좌 #29 Servo Motor SG90 라이브러리 없이 사용 (0) | 2020.08.28 |
아두이노 강좌 #27 동적 메모리 용량 부족 문제 PROGMEM F() 메크로로 해결 (1) | 2020.08.25 |
Arduino LED Matrix Spectrum Effect - Audio Spectrum Visualizer Project Part.1 (2) | 2020.08.23 |
아두이노 강좌 #26 8x8 LED 매트릭스 문자열 스크롤 하기 (0) | 2020.08.22 |