이전 버전을 개선하였다.
2022.07.09 - [프로그래밍/MFC (C++)] - MFC ] 시리얼 통신으로 LED 제어하기 (1)
깃허브 주소:
https://github.com/joeteo/MFC_test01.git
https://github.com/joeteo/LEDSerialCMD.git
MFC송신-STM32수신부분은 이전에 비해 많이 달라진게 없다.
버튼의 text도 STM32에서 100ms 마다 보내는 상태 신호를 읽어서 바뀌게 할 수 있는데 해당 부분은 수정하진 않았다.
그리고 다른 컴퓨터에서 깃 클론해서 실행해보려고 했더니 갑자기 통신이 안되서 원인을 찾아 헤멨는데 알고보니 Visual Studio 빌드 버전이 x64 로 바뀌어 있는 탓이었다.
아무튼 STM32 송신 - MFC 수신 부분을 개선했는데
STM32 송신부분에선 커맨드를 한번에 보내는 버전으로 바꿨다.
예를들어 2번 LED만 켜있다면
"L010\n" 이런식이다.
그리고 MFC 수신 부분에서는 char 타입 vector 를 멤버변수로 만들어 놓고 벡터에 담긴 값을 전부 처리하고 나가는 버전으로 바꾸었다.
STM32에선 한 바이트 단위로 수신 인터럽트가 발생하는데 MFC 에선 OnReceive 메시지가 호출 될 때 WPARAM length 와 같이 들어오고 이 length가 얼마가 될지 모르니까 벡터로 처리하는 것이 매우 효율적이다.
STM32 송신 부분
memset으로 초기화 후 strcpy로 뒤에 '\0' 을 넣는 형태로 카피하고 각각 LED와 연결된 GPIO Output 핀의 상태를 읽어서 strcat으로 뒷부분에 이어붙이다. 마지막으론 개행문자를 붙이고 폴링방식으로 100ms 간격마다 송신한다.
char temp[5];
/* USER CODE END 2 */
while (1)
{
memset(temp, 0, sizeof(temp));
strcpy(temp, "L");
if(HAL_GPIO_ReadPin(LD1_GPIO_Port, LD1_Pin)){
strcat(temp,"1");
}else{
strcat(temp,"0");
}
if(HAL_GPIO_ReadPin(LD2_GPIO_Port, LD2_Pin)){
strcat(temp,"1");
}else{
strcat(temp,"0");
}
if(HAL_GPIO_ReadPin(LD3_GPIO_Port, LD3_Pin)){
strcat(temp,"1");
}else{
strcat(temp,"0");
}
strcat(temp,"\n");
HAL_UART_Transmit(&huart3, (uint8_t*)temp, sizeof(temp), 10);
HAL_Delay(100);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
MFC 수신 부분
-Dlg.h 에 시리얼 통신으로 수신된 데이터를 한 바이트씩 담아둘 char 타입 벡터를 만들어 둔다.
vector<char> rx;
rx 벡터에 차례대로 담고 커맨드 길이가 5라서 while(rx.size() >= 5) 으로 벡터 사이즈가 5 미만으로 남을 때까지 계속 처리하고 삭제하고를 반복한 후 빠져나간다.
첫번째 if문은 시작비트가 'L'이고 종료비트가 '\n'인 커맨드 형식에 맞게 들어왔을 때 커맨드에 따른 처리를 해주고 5개 길이만큼 삭제하고
두번째 if문은 시작비트가 'L'이 아닌경우 한 요소를 지우고
세번째 if문은 시작비트는 'L'이지만 종료비트인 '\n'이 제자리에 없는 경우를 의미하며 5개 길이만큼 삭제하고
결국에는 벡터 사이즈가 5미만이 될 때까지 이런식으로 반복 처리한다.
afx_msg LRESULT CLEDSerialCMDDlg::OnReceive(WPARAM length, LPARAM lParam)
{
CString str;
char* data = new char[length + 1];
if (m_comm)
{
m_comm->Receive(data, length); // Length 길이만큼 데이터 받음.
//data[length] = _T('\0');
for (int i = 0; i < length; i++)
{
//str += data[i];
rx.push_back(data[i]);
}
while(rx.size() >= 5)
{
if (rx.at(0) == 'L' && rx.at(4) == '\n')
{
if (rx.at(1) == '1')
{
m_LD1State = _T("ON");
}
else
{
m_LD1State = _T("OFF");
}
if (rx.at(2) == '1')
{
m_LD2State = _T("ON");
}
else
{
m_LD2State = _T("OFF");
}
if (rx.at(3) == '1')
{
m_LD3State = _T("ON");
}
else
{
m_LD3State = _T("OFF");
}
rx.erase(rx.begin(), rx.begin() + 4);
}else if(rx.at(0) != 'L')
{
rx.erase(rx.begin());
}else if (rx.at(4) != '\n')
{
rx.erase(rx.begin(), rx.begin() + 4);
}
}
UpdateData(false);
//str = "";
}
delete data;
return 0;
}
'프로그래밍 > MFC (C++)' 카테고리의 다른 글
MFC ] char* -> CString , CString -> char* 변환하기 (0) | 2022.07.14 |
---|---|
MFC ] MySQL 을 활용한 도서 관리 프로그램 (1) (2) | 2022.07.14 |
MFC ] DoModal() 창 닫기, 강제 종료 (0) | 2022.07.13 |
MFC ] 리스트 컨트롤에서 클릭된 아이템 값 가져오기 (0) | 2022.07.13 |
MFC ] Visual Studio에서 MySQL 라이브러리 추가하기 (0) | 2022.07.13 |