이번 글은 stm32cubeide에서 printf문과 scanf문 사용 방법과 float, double 실수 변수 사용 방법, uart 실제 구동 코드를 정리하고자 한다.
사용 TOOL : stm32CUBEIDE
보드명 : stm32f411re nucleo board (HCLK MAX : 100HZ)
1. printf문
1) 표준 입출력 헤더파일 선언
2) 아래 __io_putchar 또는 _write 함수를 정의한다.
(1) __io_putchar
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int __io_putchar(int ch){
HAL_UART_Transmit(&huartx, &ch, 1, HAL_MAX_DELAY);
return ch;
}
/* USER CODE END 0 */
(2) _write
int _write(int fd, char* p , int len){
HAL_UART_Transmit(&huartx, (uint8_t*)p, len, HAL_MAX_DELAY);
return len;
}
2. scanf문
(1) 표준 입출력 헤더파일 선언
(2) 아래 _write 함수와 __io_getchar , __io_putchar 함수를 같이 재정의한다.
int _read(int fd, char *p, int len)
{
HAL_UART_Receive(&huartx, (unsigned char*)p, len, HAL_MAX_DELAY);
return len;
}
int __io_putchar(int ch)
{
HAL_UART_Transmit(&huartx, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
int __io_getchar(void)
{
uint8_t ch = 0;
HAL_UART_Receive(&huartx, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
scanf 사용 시, setbuf(stdin, NULL)을 설정하여 표준 입력시 버퍼를 사용하지 않게 설정해야 한다.
만약 setbuf(stdin, NULL)을 설정하지 않으면 사용자 입력상태에서 블럭상태가 유지되지 않는다.
3. 실제 구동
아래 사진은 실제 구동 예제들에 사용한 설정이다.
huart : USART1
mode : Asynchoronous
USART1의 경우 핀 설정이 아래와 같다.
인터럽트 설정시
DMA 설정시
1) Polling : 특정 주기를 가지고 그 주기 마다 처리를 위한 시그널이 들어 왔는지를 체크
(1) 수신
uint8_t ch = 0;
while (1)
{
HAL_UART_Receive(&huart1, &ch, 1, 0xFFFF);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
(2) 송신
/* Infinite loop */
/* USER CODE BEGIN WHILE */
uint8_t ch = 0;
while (1)
{
HAL_UART_Transmit(&huart1, &ch, 1, 0xFFFF);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
2) Interrupt : 프로그램이 실행되고 있을 때, 입출력 하드웨어 등의 장치 등에서 이벤트가 발생하여 처리가 필요한 경우 Processor에 알려 핸들러를 통해 처리
(1) 송신
두가지 핸들러(함수)를 반드시 기억해야 한다
1. HAL_UART_Transmit_IT
- 송신 인터럽트 대기 상태 설정
2. HAL_UART_TxCpltCallback
- UART 송신 이벤트 발생 시 , 인터럽트 발생한다.
- USARTx_IRQHandler(인터럽트 처리함수)가 실행된다.
-수신 인터럽트 경우, HAL_UART_TxCpltCallback(콜백함수) 호출하여 ISR(인터럽트 처리 루틴)이 콜백함수 내에서 처리
ex)
/* USER CODE BEGIN 0 */
uint8_t tx_buff[]={65,66,67,68,69,70,71,72,73,74}; //ABCDEFGHIJ in ASCII code
/* USER CODE END 0 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_UART_Transmit_IT(&huart1, tx_buff, 10);
HAL_Delay(10000);
}
/* USER CODE END 3 */
(2) 송신
두가지 핸들러(함수)를 반드시 기억해야 한다
1. HAL_UART_Receive_IT
- 수신 인터럽트 대기 상태 설정
2. HAL_UART_RxCpltCallback
- UART 수신 이벤트 발생 시 , 인터럽트 발생한다.
- USARTx_IRQHandler(인터럽트 처리함수)가 실행된다.
-수신 인터럽트 경우, HAL_UART_RxCpltCallback(콜백함수) 호출하여 ISR(인터럽트 처리 루틴)이 콜백함수 내에서 처리
ex)
/* USER CODE BEGIN 0 */
uint8_t rx_buff[10];
/* USER CODE END 0 */
/* USER CODE BEGIN 0 */
uint8_t rx_buff[10];
/* USER CODE END 0 */
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->instance == USART1){
HAL_UART_Receive_IT(&huart1, rx_buff, 10); // 재인터럽트 요청
}
}
/* USER CODE END 4 */
참고 사진) Polling vs Interrupt
3) DMA(Direct Memory Access, 직접 메모리 접근) : 메모리 버퍼, 포인터, 카운터를 사용하여 장치 제어기가 CPU 개입 없이 I/O device 와 memory device 사이에 데이터 입출력 방식
장점 : 많은 데이터 입출력이 필요한 경우 DMA를 사용하면 CPU는 데이터 입출력 이루어지는 동안 점유되지 않고, 다른 일을 수행할수 있다.
1. HAL_DMA_Start
2.HAL_UART_Receive_DMA
3. HAL_UART_Receive_DMA
(1) 송신
ex)
uint8_t UART1_rxBuffer[12] = {0};
UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART1_UART_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
HAL_UART_Receive_DMA (&huart1, UART1_rxBuffer, 12);
while (1)
{
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Receive_DMA(&huart1, UART1_rxBuffer, 12);
HAL_UART_Transmit(&huart1, UART1_rxBuffer, 12, 100);
}
참고 사진)
추가예제)
아래는 임의의 패킷 메세지 전달시 수신받은 메세지를 다시 송신하는 에코 동작 예제
입력 : RX 메세지 [인터럽트]
출력 : TX 메세지 [폴링]
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM3_Init();
MX_USART2_UART_Init();
uint8_t msg;
HAL_UART_Receive_IT(&huart2, (uint8_t*)&msg, 1);
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->instance == USART2){
if(HAL_UART_Receive_IT(&huart2, &msg, 1) == HAL_OK){
HAL_UART_Transmit(&huart2, &msg, 1, HAL_MAX_DELAY);
}
}
}
/* USER CODE END 4 */
추가적으로 임의의 패킷 메세지 전달시 프로토콜에 맞게 문자열 출력하는 예제를 업데이트 예정
'Stm32 > 실제 구동(stm32cubeide)' 카테고리의 다른 글
ADC Multi Channel - Joy Stick (0) | 2024.07.10 |
---|---|
UART 실습[2] (0) | 2024.06.30 |
Timer Interrupt (0) | 2024.06.18 |
[1]GPIO 입출력 레지스터 직접 제어 (0) | 2024.05.02 |
GPIO 입출력 [HAL-DRIVER 이용] (0) | 2024.05.01 |