본문 바로가기
프로그래밍/MFC (C++)

MFC ] 시리얼 통신으로 LED 제어하기 (1)

by eteo 2022. 7. 9.

 

깃허브 주소:

https://github.com/joeteo/LEDSerialCMD

 

GitHub - joeteo/LEDSerialCMD

Contribute to joeteo/LEDSerialCMD development by creating an account on GitHub.

github.com

https://github.com/joeteo/MFC_test01.git

 

GitHub - joeteo/MFC_test01

Contribute to joeteo/MFC_test01 development by creating an account on GitHub.

github.com

 

 

 

첨부된 zip파일에서 필요한 부분을 머지하고 다이얼로그의 도구들과 메시지인 OnReceive와 OnThreadClosed는 직접 추가하였다. 프로젝트 속성에서 문자집합을 멀티바이트 문자집합으로 바꿔주었다.

 

 

 

 

실제 UART로 송신을 하는 부분은 LED 버튼 이벤트 처리기 함수에서 그리고 수신을 하는 부분은 OnReceive 메시지에서 이뤄진다.

 

커맨드 예시.

"L10\n" : 1번 LED를 끈다.

"L31\n" : 3번 LED를 켠다.

 

 

 

MFC 송신 부분

void CLEDSerialCMDDlg::OnBnClickedLed1()
{
	CString str;
	static int toggle = 0;
	toggle = ~toggle;
	if (toggle) {
		str = _T("L11");
		GetDlgItem(IDC_LED1)->SetWindowText(_T("LED1 OFF"));
	}
	else {
		str = _T("L10");
		GetDlgItem(IDC_LED1)->SetWindowText(_T("LED1 ON"));
	}		

	str += _T("\n");
	m_comm->Send(str, str.GetLength());
}


void CLEDSerialCMDDlg::OnBnClickedLed2()
{
	CString str;
	static int toggle = 0;
	toggle = ~toggle;
	if (toggle) {
		str = _T("L21");
		GetDlgItem(IDC_LED2)->SetWindowText(_T("LED2 OFF"));
	}
	else {
		str = _T("L20");
		GetDlgItem(IDC_LED2)->SetWindowText(_T("LED2 ON"));
	}

	str += _T("\n");
	m_comm->Send(str, str.GetLength());
}


void CLEDSerialCMDDlg::OnBnClickedLed3()
{
	CString str;
	static int toggle = 0;
	toggle = ~toggle;
	if (toggle) {
		str = _T("L31");
		GetDlgItem(IDC_LED3)->SetWindowText(_T("LED3 OFF"));
	}
	else {
		str = _T("L30");
		GetDlgItem(IDC_LED3)->SetWindowText(_T("LED3 ON"));
	}

	str += _T("\n");
	m_comm->Send(str, str.GetLength());
}

 

static 으로 변수 선언해서 토글시켰고,

GetDlgItem()->SetWindowText() 를 활용하여 변수 추가 없이 버튼의 텍스트를 변경하였다.

 

 

 

 

MFC 수신부분

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');
		//str += _T("\r\n");
		for (int i = 0; i < length; i++)
		{
			str += data[i];
		}
		std::string temp = CT2CA(str);
		const char* p;
		if ((p = strstr(temp.c_str(), "L")) != 0) {
			uint8_t lednum = *(p + 1) - '0';
			uint8_t ledstate = *(p + 2) - '0';

			if(lednum==1)
			{
				if (ledstate == 1) m_LD1State = _T("켜짐");
				else m_LD1State = _T("꺼짐");

			}
			else if (lednum == 2)
			{
				if (ledstate == 1) m_LD2State = _T("켜짐");
				else m_LD2State = _T("꺼짐");
			}
			else if (lednum == 3)
			{
				if (ledstate == 1) m_LD3State = _T("켜짐");
				else m_LD3State = _T("꺼짐");
			}


		}
		UpdateData(false);
		

		//m_edit_rcv_view.ReplaceSel(str);
		//str = "";
		//m_edit_rcv_view.LineScroll(m_edit_rcv_view.GetLineCount());

		str = "";
	}
	delete data;

	return 0;
}

 

 

 

 

 

 

STM32 수신 인터럽트 처리 부분

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance == USART3){
		if(rx_flag==0 && rx3_data=='L'){
			buf_index=0;
			memset(buf,0,sizeof(buf));
			rx_flag=1;
		}

		if(rx_flag==1){
			if(rx3_data !='\n' && buf_index < 10){
				buf[buf_index++]=rx3_data;
			}else{
				char *p;
				if((p = strstr((char*)buf,"L")) != 0){
					uint8_t lednum = (*(p+1)-'0')-1;
					uint8_t ledstate = *(p+2)-'0';
					HAL_GPIO_WritePin(LDPortarr[lednum], LDPinarr[lednum], ledstate);

					rx_flag=0;
				}
			}
		}


		HAL_UART_Receive_IT(&huart3, &rx3_data, 1);
	}
}
/* USER CODE END 4 */

 

 

 

 

 

STM32 while문 내에서 송신하는 부분

미처 커밋을 못해서 자료가 없다.

커맨드는 예를 들어 3번 LED만 켜져있었을 때 이런 식이었다.

"L10\n"

"L20\n"

"L31\n"

 

 

시간이 부족해 대충 만들어본 버전이다. 이후 MFC로 다이나믹셀 서보를 제어하는 걸 해보고 싶기 때문에 그 때 공들여서 만들어 보도록 하겠다.

 

 

 

 

참고.

 

 

 

 

 

머지 과정 기록.

 

SerialCom.h

SerialCom.cpp

stdafx.h

stdafx.cpp

추가하고

나머지는 -Dlg.h -Dlg.cpp 에서 필요한 부분만 보면서 가져온다.

 

다이얼로그에 연결 버튼과 콤보박스 IDC_COMBO_COMPORT 랑 IDC_COMBO_BAUDRATE 추가하고 각각 멤버변수를 컨트롤과 값으로 만든다.

CComboBox m_combo_comport_list;
CComboBox m_combo_baudrate_list;
CString m_str_comport;
CString m_combo_baudrate;

 

콤보박스들은 CbnSelchange 이벤트 처리기 함수 만들어주고

연결버튼은 BnClickedBt 처리기 함수 추가한다.

 

OnReceive랑 OnThreadClosed 메시지는 클래스마법사에서 직접 추가해도 되고 

이미 SerialCom.h에 WM_MYRECEIVE, WM_MYCLOSE 으로 define 되어 있다.

 

그 안의 내용은 긁어오고 데이터 수신부분은 onRecevie에 있고 송신부분은 해당하는 버튼 이벤트처리기 함수 안에 있으니 본인의 프로토콜에 맞게 수정해서 쓰면 된다.