[STM32#15] C# winform을 이용해서 STM32f103rb nucleo보드와 usart2로 시리얼(serial)통신하는 방법 알아보기!(녹칸다 내맘대로 STM32)
프로그래밍/STM32 2025. 12. 1. 23:17
https://youtube.com/live/Q39rzRj1ol8
[STM32#15] C# winform을 이용해서 STM32f103rb nucleo보드와 usart2로 serial통신하는 방법 알아보기!(녹칸다 내맘대로 STM32)
심심한녹칸다의 내맘대로 STM32시리즈이다!
STM32시리즈의 모든 자료는 구글 슬라이드에 작성하고 모두에게 공유되어있음!
https://docs.google.com/presentation/d/1myA5iYbjuKsLWLqtRLKAiRfwUwvqB1d1RGjiMIIgp3I/edit?slide=id.g3ab9129297f_1_25#slide=id.g3ab9129297f_1_25
이번편 부터 STM32의 친구 C#윈폼이 등장합니다!
1.STM32가 1초간격으로 “I’m stm32 board!!”라는 문자열을 PC로 전송할때, C#윈폼으로 만든 프로그램화면에 받은 문자열을 그대로 출력하시오!

/* USER CODE BEGIN 2 */
char msg[] = "I'm STM32 BOARD!!\n";
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//1초간격으로 지정된 문자열을 전송한다
HAL_UART_Transmit(&huart2,msg,strlen(msg),100);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
private void button1_Click(object sender, EventArgs e)
{
//button1이 클릭된게 감지되었는데 너 뭐할래?
serialPort1.PortName = textBox1.Text;
serialPort1.BaudRate = 115200;
serialPort1.Open(); //포트 개방!
if (serialPort1.IsOpen)
{
//버퍼에 있는 데이터를 모조리 소멸시킨다
serialPort1.ReadExisting();
MessageBox.Show("접속완료!");
}
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
//stm32에서 데이터가 수신되었다! 뭐할래?
//stm32가 보낸 문자열중 종료문자가 LF일때 까지를 읽겠다!
string data = serialPort1.ReadLine();
richTextBox1.Text += data + "\n";
}
2.STM32에서 PB1에 연결된 버튼을 누르면 BTN1 CLICK!이라고 전송하고 PA8에 연결된 버튼을 누르면 BTN2 CLICK이라고 전송해서 C#윈폼으로 만든 GUI에 출력한다!

/* USER CODE BEGIN 2 */
char msg1[] = "BTN1 CLICKED!\n";
char msg2[] = "BTN2 CLICKED!\n";
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//PB1을 누르면~
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == 0){
HAL_UART_Transmit(&huart2,msg1,strlen(msg1),100);
HAL_Delay(300);
}
//PA8을 누르면~
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == 0){
HAL_UART_Transmit(&huart2,msg2,strlen(msg2),100);
HAL_Delay(300);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
private void button1_Click(object sender, EventArgs e)
{
//button1이 클릭된게 감지되었는데 너 뭐할래?
serialPort1.PortName = textBox1.Text;
serialPort1.BaudRate = 115200;
serialPort1.Open(); //포트 개방!
if (serialPort1.IsOpen)
{
//버퍼에 있는 데이터를 모조리 소멸시킨다
serialPort1.ReadExisting();
MessageBox.Show("접속완료!");
}
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
//stm32에서 데이터가 수신되었다! 뭐할래?
//stm32가 보낸 문자열중 종료문자가 LF일때 까지를 읽겠다!
string data = serialPort1.ReadLine();
richTextBox1.Text += data + "\n";
}
3.예제2에서 PB1을 누르면 STM32내부에 있는 uint32_t num1 = 1234;의 값을 C#윈폼으로 바이너리로 전송하고, PA8을 누르면 int32_t num2 = -5678;의 값을 C#으로 전송해서 출력하시오!

/* USER CODE BEGIN 2 */
uint32_t num1 = 1234;
int32_t num2 = -5678;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//PB1을 누르면~
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == 0){
HAL_UART_Transmit(&huart2,(uint8_t*)&num1,sizeof(num1),100);
HAL_Delay(300);
}
//PA8을 누르면~
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == 0){
HAL_UART_Transmit(&huart2,(uint8_t*)&num2,sizeof(num2),100);
HAL_Delay(300);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
private void button1_Click(object sender, EventArgs e)
{
//button1이 클릭된게 감지되었는데 너 뭐할래?
serialPort1.PortName = textBox1.Text;
serialPort1.BaudRate = 115200;
serialPort1.Open(); //포트 개방!
if (serialPort1.IsOpen)
{
//버퍼에 있는 데이터를 모조리 소멸시킨다
serialPort1.ReadExisting();
MessageBox.Show("접속완료!");
}
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
//stm32에서 데이터가 수신되었다! 뭐할래?
//4byte로 구성된 숫자가 날라오는 상황이 되었다!
byte[] buff = new byte[4];
//STM32가 보낸 데이터를 buff에 0번부터 시작해서
//4개를 가져와서 대입하겠다!
serialPort1.Read(buff, 0, 4);
//buff안에 들어있는 값을 0부터 4개를 uint32로 해석!
UInt32 num1 = BitConverter.ToUInt32(buff, 0);
Int32 num2 = BitConverter.ToInt32(buff, 0);
richTextBox1.Text = num1 + ", " + num2;
}
4.C#에서 ON버튼과 OFF버튼을 2개 생성하고, ON버튼을 누르면 PB3에 연결된 LED를 ON하고 OFF버튼은 OFF시키시오!(문자 ‘0’일때 OFF, 문자 ‘1’일때 ON)

/* USER CODE BEGIN 2 */
char recv;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(HAL_UART_Receive(&huart2, &recv, 1, 500) == HAL_OK){
//C#에서 보낸 데이터 1개를 성공적으로 수신함!
if(recv == '0'){
//LED OFF
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 0);
}else if(recv == '1'){
//LED ON
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 1);
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
private void button1_Click(object sender, EventArgs e)
{
//button1이 클릭된게 감지되었는데 너 뭐할래?
serialPort1.PortName = textBox1.Text;
serialPort1.BaudRate = 115200;
serialPort1.Open(); //포트 개방!
if (serialPort1.IsOpen)
{
//버퍼에 있는 데이터를 모조리 소멸시킨다
serialPort1.ReadExisting();
MessageBox.Show("접속완료!");
}
}
private void button3_Click(object sender, EventArgs e)
{
//OFF버튼 문자 '0'전송
if (serialPort1.IsOpen)
{
serialPort1.Write("0");
}
else
{
MessageBox.Show("접속을 해주세요!");
}
}
private void button2_Click(object sender, EventArgs e)
{
//ON버튼 문자 '1'전송
if (serialPort1.IsOpen)
{
serialPort1.Write("1");
}
else
{
MessageBox.Show("접속을 해주세요!");
}
}
5.C#에서 ON버튼과 OFF버튼을 2개 생성하고, ON버튼을 누르면 PB3에 연결된 LED를 ON하고 OFF버튼은 OFF시키시오!(숫자 0일때 OFF, 숫자 1일때 ON)

/* USER CODE BEGIN 2 */
char recv;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(HAL_UART_Receive(&huart2, &recv, 1, 500) == HAL_OK){
//C#에서 보낸 데이터 1개를 성공적으로 수신함!
//녹칸다가 recv에 0을 보내면 LED OFF신호고 바로 적용하고
//1을 보내면 ON신호로 바로 적용가능하나,
//만약 C#에서 0,1 이외에 다른걸 보내게되면 문제가 생길수있음!
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, recv);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
private void button1_Click(object sender, EventArgs e)
{
//button1이 클릭된게 감지되었는데 너 뭐할래?
serialPort1.PortName = textBox1.Text;
serialPort1.BaudRate = 115200;
serialPort1.Open(); //포트 개방!
if (serialPort1.IsOpen)
{
//버퍼에 있는 데이터를 모조리 소멸시킨다
serialPort1.ReadExisting();
MessageBox.Show("접속완료!");
}
}
private void button3_Click(object sender, EventArgs e)
{
//OFF버튼 문자 '0'전송
if (serialPort1.IsOpen)
{
//숫자 1개 전송하기!
byte[] data = { 0 };
serialPort1.Write(data, 0, 1);
}
else
{
MessageBox.Show("접속을 해주세요!");
}
}
private void button2_Click(object sender, EventArgs e)
{
//ON버튼 문자 '1'전송
if (serialPort1.IsOpen)
{
//숫자 1개 전송하기!
byte[] data = { 1 };
serialPort1.Write(data, 0, 1);
}
else
{
MessageBox.Show("접속을 해주세요!");
}
}
6.PB3,PB13,PB5,PB14,PB4,PB15,PC4,PB7에 LED가 총 8개 연결되어있는데, C#윈폼에서 버튼을 이용해서 모든 LED를 제어할 수 있는 UI와 기능을 구현하시오!
-문자0,1(LED1), 문자2,3(LED2), 문자4,5(LED3), 문자6,7(LED4), 문자8,9(LED5), 문자A,B(LED6), 문자C,D(LED7), 문자E,F(LED8)

/* USER CODE BEGIN 2 */
char recv;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(HAL_UART_Receive(&huart2, &recv, 1, 500) == HAL_OK){
if(recv == '0'){
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 0);
}else if(recv == '1'){
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 1);
}else if(recv == '2'){
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, 0);
}else if(recv == '3'){
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, 1);
}else if(recv == '4'){
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 0);
}else if(recv == '5'){
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 1);
}else if(recv == '6'){
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, 0);
}else if(recv == '7'){
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, 1);
}else if(recv == '8'){
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 0);
}else if(recv == '9'){
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 1);
}else if(recv == 'A'){
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, 0);
}else if(recv == 'B'){
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, 1);
}else if(recv == 'C'){
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, 0);
}else if(recv == 'D'){
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, 1);
}else if(recv == 'E'){
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, 0);
}else if(recv == 'F'){
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, 1);
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
private void button1_Click(object sender, EventArgs e)
{
//button1이 클릭된게 감지되었는데 너 뭐할래?
serialPort1.PortName = textBox1.Text;
serialPort1.BaudRate = 115200;
serialPort1.Open(); //포트 개방!
if (serialPort1.IsOpen)
{
//버퍼에 있는 데이터를 모조리 소멸시킨다
serialPort1.ReadExisting();
MessageBox.Show("접속완료!");
}
}
private void button3_Click(object sender, EventArgs e)
{
serialPort1.Write("0");
}
private void button2_Click(object sender, EventArgs e)
{
serialPort1.Write("1");
}
private void button5_Click(object sender, EventArgs e)
{
serialPort1.Write("2");
}
private void button4_Click(object sender, EventArgs e)
{
serialPort1.Write("3");
}
private void button7_Click(object sender, EventArgs e)
{
serialPort1.Write("4");
}
private void button6_Click(object sender, EventArgs e)
{
serialPort1.Write("5");
}
private void button9_Click(object sender, EventArgs e)
{
serialPort1.Write("6");
}
private void button8_Click(object sender, EventArgs e)
{
serialPort1.Write("7");
}
private void button16_Click(object sender, EventArgs e)
{
serialPort1.Write("8");
}
private void button17_Click(object sender, EventArgs e)
{
serialPort1.Write("9");
}
private void button14_Click(object sender, EventArgs e)
{
serialPort1.Write("A");
}
private void button15_Click(object sender, EventArgs e)
{
serialPort1.Write("B");
}
private void button12_Click(object sender, EventArgs e)
{
serialPort1.Write("C");
}
private void button13_Click(object sender, EventArgs e)
{
serialPort1.Write("D");
}
private void button10_Click(object sender, EventArgs e)
{
serialPort1.Write("E");
}
private void button11_Click(object sender, EventArgs e)
{
serialPort1.Write("F");
}
7.예제6번을 조금더 고급스럽게, 효율적으로 바꿔보시오! 추가로 모든 LED를 ON하고나 OFF하는 기능을 추가하시오!

/* USER CODE BEGIN 2 */
GPIO_TypeDef *mygpio[] = {GPIOB,GPIOB,GPIOB,GPIOB,GPIOB,GPIOB,GPIOC,GPIOB};
uint16_t mypin[] = {GPIO_PIN_3,GPIO_PIN_13,GPIO_PIN_5,GPIO_PIN_14,GPIO_PIN_4,GPIO_PIN_15,GPIO_PIN_4,GPIO_PIN_7};
char recv[2];
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(HAL_UART_Receive(&huart2, recv, 2, 500) == HAL_OK){
//recv[0] : LED번호
int led_num = recv[0];
//recv[1] : 0이면 OFF, 1이면 ON
int state = recv[1];
if(led_num == 8){
//led_num이 8이면 모든 LED를 제어하는 것이다!
for(int i = 0;i<8;i++){
HAL_GPIO_WritePin(mygpio[i], mypin[i], state);
}
}else{
HAL_GPIO_WritePin(mygpio[led_num], mypin[led_num], state);
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
private void button1_Click(object sender, EventArgs e)
{
//button1이 클릭된게 감지되었는데 너 뭐할래?
serialPort1.PortName = textBox1.Text;
serialPort1.BaudRate = 115200;
serialPort1.Open(); //포트 개방!
if (serialPort1.IsOpen)
{
//버퍼에 있는 데이터를 모조리 소멸시킨다
serialPort1.ReadExisting();
MessageBox.Show("접속완료!");
}
}
private void button3_Click(object sender, EventArgs e)
{
byte[] data = { 0, 0 };
serialPort1.Write(data, 0, 2);
}
private void button2_Click(object sender, EventArgs e)
{
byte[] data = { 0,1 };
serialPort1.Write(data, 0, 2);
}
private void button5_Click(object sender, EventArgs e)
{
byte[] data = { 1, 0 };
serialPort1.Write(data, 0, 2);
}
private void button4_Click(object sender, EventArgs e)
{
byte[] data = { 1, 1 };
serialPort1.Write(data, 0, 2);
}
private void button7_Click(object sender, EventArgs e)
{
byte[] data = { 2, 0 };
serialPort1.Write(data, 0, 2);
}
private void button6_Click(object sender, EventArgs e)
{
byte[] data = { 2, 1 };
serialPort1.Write(data, 0, 2);
}
private void button9_Click(object sender, EventArgs e)
{
byte[] data = { 3, 0 };
serialPort1.Write(data, 0, 2);
}
private void button8_Click(object sender, EventArgs e)
{
byte[] data = { 3, 1 };
serialPort1.Write(data, 0, 2);
}
private void button16_Click(object sender, EventArgs e)
{
byte[] data = { 4, 0 };
serialPort1.Write(data, 0, 2);
}
private void button17_Click(object sender, EventArgs e)
{
byte[] data = { 4, 1 };
serialPort1.Write(data, 0, 2);
}
private void button14_Click(object sender, EventArgs e)
{
byte[] data = { 5, 0 };
serialPort1.Write(data, 0, 2);
}
private void button15_Click(object sender, EventArgs e)
{
byte[] data = { 5, 1 };
serialPort1.Write(data, 0, 2);
}
private void button12_Click(object sender, EventArgs e)
{
byte[] data = { 6, 0 };
serialPort1.Write(data, 0, 2);
}
private void button13_Click(object sender, EventArgs e)
{
byte[] data = { 6, 1 };
serialPort1.Write(data, 0, 2);
}
private void button10_Click(object sender, EventArgs e)
{
byte[] data = { 7, 0 };
serialPort1.Write(data, 0, 2);
}
private void button11_Click(object sender, EventArgs e)
{
byte[] data = { 7, 1 };
serialPort1.Write(data, 0, 2);
}
private void button18_Click(object sender, EventArgs e)
{
byte[] data = { 8, 1 };
serialPort1.Write(data, 0, 2);
}
private void button19_Click(object sender, EventArgs e)
{
byte[] data = { 8, 0 };
serialPort1.Write(data, 0, 2);
}

