왜 행에 High를 주고 열에 Low 를 줘야되는지 모르겠다면 아래 링크를 보고 오자.
https://program-developers-story.tistory.com/21
위 그림의 핀의 숫자는 모듈의 물리적인 핀 번호를 의미함. 행은 실제 매트릭스에 표시되는 행이나 열을 의미함.
pin1~8이 그림 상에는 PD0~PD7로 나와있고, pin9~16이 그림 상에는 PC0~PC7로 나와 있다.
만약 윗 그림과 같이 연결하려면 ioc파일에서 사용할 핀을 그것에 맞게 세팅해주면 된다.
비트 시프트 연산을 활용해서 8x8 matrix의 dot를 표현할 것이기 때문에 핀은 인접한 핀들로 해주어야 한다.
그림과 다르게 실제로 연결은 아래와 같이 하였다.
pin1 -> PD4 / pin2 -> PD6 / pin3 -> PE3 / pin4 -> PE4 / pin5 -> PD7 / pin6 -> PE6 / pin7 -> PD5 / pin8 -> PD2
pin9 -> PD0 / pin10 -> PE5 / pin11 -> PE7 / pin12 -> PD3 / pin13 -> PE2 / pin14 -> PD1 / pin15 -> PE8 / pin16 -> PE9
앞서 말했듯 회로도 상 저항 있는 핀들은 저항을 꽂아주면 된다.
그럼 이제 CUBE IDE를 열고, HW 연결대로 ioc 파일 세팅을 해주면 되는데 아래의 코드를 그대로 사용하기 위해서는 pin 번호에 맞게 labeling을 해줘야한다. pin setting은 모두 GPIO_OUTPUT이고 pin1~pin8을 COL1~COL8로 user labeling해주고, pin9~pin16을 ROW1~ ROW8로 user labeling해주면 되겠다.
Online led matrix font generator with binary and hex codes for Arduino
여기 링크에서 8bit binary형태의 8칸 배열 생성 가능, 생성 후 아래 unsigned char처럼 변수명 주고 B를 0b로 바꿔서 넣어주면 됨.
아래의 코드를 dotmatrix.c 파일을 생성 후 복붙
#include "dotmatrix.h"
GPIO_TypeDef *col_port[]=
{
COL1_GPIO_Port,COL2_GPIO_Port,COL3_GPIO_Port,COL4_GPIO_Port,
COL5_GPIO_Port,COL6_GPIO_Port,COL7_GPIO_Port,COL8_GPIO_Port
};
GPIO_TypeDef *row_port[]=
{
ROW1_GPIO_Port,ROW2_GPIO_Port,ROW3_GPIO_Port,ROW4_GPIO_Port,
ROW5_GPIO_Port,ROW6_GPIO_Port,ROW7_GPIO_Port,ROW8_GPIO_Port
};
uint16_t col_pin[] =
{
COL1_Pin,COL2_Pin,COL3_Pin,COL4_Pin,
COL5_Pin,COL6_Pin,COL7_Pin,COL8_Pin
};
uint16_t row_pin[] =
{
ROW1_Pin,ROW2_Pin,ROW3_Pin,ROW4_Pin,
ROW5_Pin,ROW6_Pin,ROW7_Pin,ROW8_Pin
};
unsigned char all_on[] =//all on 문자 정의
{
0b11111111,
0b11111111,
0b11111111,
0b11111111,
0b11111111,
0b11111111,
0b11111111,
0b11111111
};
unsigned char woo[] =
{
0b00011000,
0b00100100,
0b01000010,
0b00111100,
0b00000000,
0b11111111,
0b00011000,
0b00011000
};
unsigned char chang[] =
{
0b00100100,
0b11111100,
0b00100100,
0b01010111,
0b10001100,
0b01110100,
0b10001100,
0b01110000
};
unsigned char min[] =
{
0b00000010,
0b01111010,
0b01001010,
0b01001010,
0b01111010,
0b00000010,
0b00100000,
0b00111110
};
void write_column_data(int col)
{
for(int i = 0; i < 8; i++)
{
if(i == col)
{
HAL_GPIO_WritePin(col_port[i], col_pin[i], 0);//on
}
else
{
HAL_GPIO_WritePin(col_port[i], col_pin[i], 1);//off
}
}
}
void write_row_data(unsigned char data)
{
unsigned char d;
d = data;//0b00111100
for(int j = 0; j < 8; j++)
{
if (d & (1 << j))//1을 0만큼 shift하면 00000001 , 1만큼 shift하면 00000010 그걸 data와 AND연산
{
HAL_GPIO_WritePin(row_port[j],row_pin[j],1);
}
else
{
HAL_GPIO_WritePin(row_port[j],row_pin[j],0);
}
}
}
int dotmatrix_main_test(void)
{
static int index=0;
//공통 양극 방식 도트매트릭스
//COL High, ROW Low
if(index < 200)
{
for(int idx = 0; idx < 8; idx++)
{
write_column_data(idx);
write_row_data(woo[idx]);
HAL_Delay(1);
}
}
else if(index>200&&index<400)
{
for(int idx = 0; idx < 8; idx++)
{
write_column_data(idx);
write_row_data(chang[idx]);
HAL_Delay(1);
}
}
else if(index>400&&index<600)
{
for(int idx = 0; idx < 8; idx++)
{
write_column_data(idx);
write_row_data(min[idx]);
HAL_Delay(1);
}
}
if(index==600)
{
index=0;
}
index++;
return 0;
}
dotmatrix.h
#include "main.h"
void write_column_data(int col);
void write_row_data(unsigned char data);
int dotmatrix_main_test(void);
자 이제 main.h에 가서 #include "dotmatrix.h"를 해주고, main.c의 main문에 while(1) 내부에 dotmatrix_main_test();를 추가해주면 된다.
결과는 아래와 같다. 동영상으로 보면 1초에 60 frame이기 때문에 1행 단위로 업데이트 되는것이 보이지만, 실제로 사람눈은 그렇게 민감하지 않기 때문에 정상적으로 켜져있는 것으로 보인다.
만약 글자가 더 빠르게 혹은 느리게 변하기를 원한다면 dotmatrix_main_test함수 내부의 index를 비교하는 조건문의 조건을 낮추거나 높이면 된다.
'Firmware Programming' 카테고리의 다른 글
[Firmware] 임베디드, 펌웨어의 차이는? (0) | 2024.02.08 |
---|---|
[Arduino] Arduino Wifi Module (ESP8266) 활용 윈도우 pc로 데이터 전송 (0) | 2024.01.31 |
[임베디드 기초 상식] 장치의 부팅 과정 (0) | 2023.10.25 |
[STM32F429ZI] Block Diagram (0) | 2023.10.25 |
[STM32F429ZI] 타이머의 종류 (0) | 2023.10.24 |