이글의 전부 또는 일부, 사진, 소스프로그램 등은 저작자의 동의 없이는 상업적인 사용을 금지합니다. 또한, 비상업적인 목적이라하더라도 출처를 밝히지 않고 게시하는 것은 금지합니다.



앞의 글 미세먼지 센서 SDS011 사용하기의 프로그램에서 몇 가지 문제가 발생해서 약간 개선합니다.

첫번째 문제점은 USART1_IRQHandler() 함수에서 무조건 10개의 데이터를 받아서 표시하기 때문에, 첫 바이트부터 받지 못하면 엉뚱한 값이 표시되는 점입니다. 이를 해결하기 위해서 USART1_IRQHandler() 함수를 다음과 같이 수정합니다.

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
  if ((__HAL_UART_GET_FLAG(&SDS011, UART_FLAG_RXNE) != RESET))
  {
    SDS011Msg[SDS011idx] = (uint8_t)(SDS011.Instance->DR & (uint8_t)0x00FF);
    if(SDS011idx == 0)
    {
    	if(SDS011Msg[SDS011idx] == 0xAA) SDS011idx = 1;
    }
    else if(SDS011idx == 1)
    {
    	SDS011idx = (SDS011Msg[SDS011idx] == 0xC0 ? 2:0);
    }
    else if(SDS011idx < SDS011_MESSAGE_LENGTH - 1) SDS011idx++;
    else
    {
      intFlag |= INT_UART_SDS011;
    }
  }
  __HAL_UART_CLEAR_PEFLAG(&SDS011); /* clear event flag */
  return;
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}



받은 데이터를 검사해서 첫바이트와 두번째 바이트를 검사하여, 헤더 값인 0xAA, 0xC0와 같은지 확인하고 같지 않으면 다시 처음부터 대기하도록 합니다.

위의 방법은 아주 간단하게 처리하는 방법입니다. 이 방법 보다는 stm32f407을 다루면서 썼던 글 STM32F407로 ESP8266 제어하기에서 다룬 Queue를 이용하는 방법을 사용하는 것이 더 좋은 해결 방법이라고 생각합니다.


두번째 문제점은 잘못된 정보를 출력하고 난 다음에 그 잘못된 정보가 지워지지 않고 남아 있는 경우가 발생한다는 점입니다. 오류 메시지를 출력하고 나서 그 메시지를 지우지 않기 때문에, 화면에 쓸데 없는 정보가 남아 있게 됩니다. 이 문제를 해결하기 위해서 출력하기 전에 출력할 영역을 먼저 지울 필요가 있습니다. 이 문제점을 해결하기 위해서 그래픽 lcd의 일정 영역을 지우는 함수를 만들 필요가 있습니다. 이 함수 이름을 일단 GlcdGraphicClearBox()로 정합니다.

그래픽 lcd의 일정 영역을 지우는 함수 GlcdGraphicClearBox()의 함수 원형을 다음과 같이 M19264Display.h에에 선언하고, 함수는 M19264Display.c 파일 안에 작성합니다.

우선 M19264Display.h에 추가할 내용입니다.

void GlcdGraphicClearBox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);


M19264Display.c에 추가할 내용입니다.

void GlcdGraphicClearBox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
	uint16_t i, j;

	if(x2 < x1)
	{
		i = x2;
		x2 = x1;
		x1 = i;
	}
	if(y2 < y1)
	{
		i = y2;
		y2 = y1;
		y1 = i;
	}

	y1 = (y1 / BITSPERBYTE) * BITSPERBYTE;
	y2 = (y2 / BITSPERBYTE + 1) * BITSPERBYTE - 1;
	for(j = y1;j < y2;j += BITSPERBYTE)
	{
		for(i = x1;i < x2;i++)
		{
			GlcdGraphicGotoxy(i, j);
			GlcdWriteData(0);
		}
	}
	GlcdGraphicGotoxy(x1, y1);
}



main() 함수 안의 while() 문을 다음과 같이 수정합니다.

  while (1)
  {
    if(intFlag & INT_TIM2_AM2302)
    {
      intFlag &= ~INT_TIM2_AM2302;
      ret = AM2302ReadData(&data);
      if(ret == AM2302_SUCCESS)
      {
        GlcdGraphicClearBox(0, 0, 191, 15);
        //GlcdGraphicGotoxy(0, 0);
        printf("¿Âµµ:%3d.%d\n", data.temp / 10, data.temp % 10);
        GlcdGraphicGotoxy(TEMP_SECOND_COL, 0);
        printf("½Àµµ:%3d.%d\n", data.humid / 10, data.humid % 10);
      }
      else
      {
        GlcdGraphicClear();
        printf("Read Error(%d)\n", ret);
      }
    }
    if(intFlag & INT_UART_SDS011)
    {
      intFlag &= ~INT_UART_SDS011;
      SDS011idx = 0;
      pm25 = SDS011Msg[3] * 256 + SDS011Msg[2];
      pm10 = SDS011Msg[5] * 256 + SDS011Msg[4];
      GlcdGraphicClearBox(0, 16, 191, 47);
      //GlcdGraphicGotoxy(0, 16);
      printf("PM25:%3d.%d\n", pm25 / 10, pm25 % 10);
      GlcdGraphicGotoxy(TEMP_SECOND_COL, 16);
      printf("PM10:%3d.%d\n", pm10 / 10, pm10 % 10);
      p1 = pState[pm25 <= PM25_GOOD ? 0:(pm25 <= PM25_COMMON ? 1:(pm25 <= PM25_BAD ? 2:3))];
      p2 = pState[pm10 <= PM10_GOOD ? 0:(pm25 <= PM10_COMMON ? 1:(pm25 <= PM10_BAD ? 2:3))];
      GlcdGraphicGotoxy(TEMP_VALUE_COL - 3 * ASCII_FONTSIZE_X, 32);
      printf("%8s\n",  p1);
      GlcdGraphicGotoxy(TEMP_SECOND_COL + TEMP_VALUE_COL - 3 * ASCII_FONTSIZE_X, 32);
      printf("%8s\n",  p2);
    }
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }


 

세번째 문제점은 굳이 DisplayChar() 함수를 사용할 필요가 없었다는 점입니다. printf() 함수를 쓰기 위해 _write() 함수를 정의해서 사용했습니다. 이전의 _write() 함수는 DisplayChar() 함수를 호출했는데, DisplayChar() 함수의 내용이 이미 GlcdGraphicPuts() 함수에 구현되어 있기 때문에, DisplayChar() 함수를 삭제하고 다음과 같이 사용하도록 했습니다.

 

/* USER CODE BEGIN 4 */
int _write(int file, char *ptr, int len)
{
  HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, RESET);
  *(ptr + len) = 0;
  GlcdGraphicPuts((uint8_t *)ptr);
  HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, SET);
  return len;
}

/* USER CODE END 4 */



동작하는 소스프로그램입니다.


STM32F103AIR.zip



블로그 이미지

엠쿠스

Microprocessor(STM32, AVR)로 무엇인가를 만들어 보고자 학습 중입니다.

,