USARTの送信と受信/printf文の設定
CUBE MXのコード生成の設定は、LL(Low Layer Library)でおこなっています。
| コネクタ | 番号 | 名称 | |
|---|---|---|---|
| CN10 | 35 | RA2 | USART2 TX |
| CN10 | 36 | RA3 | USART2 RX |
USART2は、STLINKに配線されているので、別途配線する必要はなし。USB経由で、通信する。
printf文を使うためにすること
syscalls.cのなかにある
extern int __io_putchar(int ch) attribute((weak)); を
自分のファイルで、同名で関数を記述する。weakアトリビュートなので、上書き優先。F446REのレジスタで動く内容を記述しておく。printf文が、文字列を作成した後、その文字列を出力するために使用する関数。
printfの下層インターフェース関数の作りこみ
void putch(USART_TypeDef *_USARTx, uint8_t ch)
{
if((_USARTx->SR & USART_SR_TXE)==USART_SR_TXE)
{
_USARTx->DR = ch;
while((_USARTx->SR&USART_SR_TXE)==0);
}
}
int __io_putchar(int ch)//<-printfが最終的に読み出す
{
putch(USART2,ch);
return 0;
}
それと同時に、標準入出力のバッファを無効化しておく。ここは、C99コンパイラの機構の問題。
setbuf(stdout,NULL);//Printfのバッファ無効化
この一文がないと、出力されない。
これで、STM32で、printf文を使用できるようになります。
USARTのコード
peripheral.h
#ifndef INC_PERIPHERAL_H_
#define INC_PERIPHERAL_H_
#include "main.h"
#include <stdio.h>
#include <stdbool.h>
//USART---------------------------------------------
#define USART_RX_BUFFER_LENGTH_MAX 30
typedef struct
{
uint8_t buf[USART_RX_BUFFER_LENGTH_MAX];
uint32_t length;
bool rxCompleted;
}_usartRXdata;
extern _usartRXdata USART2RX;
extern void putch(USART_TypeDef *_USARTx, uint8_t ch);
extern void USART_SendData(USART_TypeDef *_USARTx, uint8_t *buf, uint8_t _len);
extern void USART_Initialize_Printf(void);
#endif /* INC_PERIPHERAL_H_ */
peripheral.c
#include "peripheral.h"
//USART----------------------------------------------------------------------
_usartRXdata USART2RX;
/**
* @brief 一文字出力
* @param USART_TypeDef
* @param ch
*/
void putch(USART_TypeDef *_USARTx, uint8_t ch)
{
if((_USARTx->SR & USART_SR_TXE)==USART_SR_TXE)
{
_USARTx->DR = ch;
while((_USARTx->SR&USART_SR_TXE)==0);
}
}
/**
* @breif 多文字出力
* @param USART_TypeDef
* @param *buf 出力バッファ
* @param _len 長さ
*/
void USART_SendData(USART_TypeDef *_USARTx, uint8_t *buf, uint8_t _len)
{
uint8_t i;
i=0;
do{
_USARTx->DR=buf[i++];
while((_USARTx->SR&USART_SR_TXE)==0);
_len--;
}while(_len);
}
/*
* printf文がバッファを使用しないように設定する関数。
* printf文を使う前に、一回実行する。
*/
void USART_Initialize_Printf()
{
setbuf(stdout,NULL);//Printfのバッファ無効化
}
/*
* @brief printf文の下層処理用関数
*/
int __io_putchar(int ch)
{
putch(USART2,ch);
return 0;
}
割り込み処理
stm32fxx_it.c
/**
* @brief This function handles USART2 global interrupt.
*/
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
/* USER CODE END USART2_IRQn 0 */
/* USER CODE BEGIN USART2_IRQn 1 */
uint8_t ch;
if((USART2->SR&USART_SR_RXNE)==USART_SR_RXNE)
{
ch=USART2->DR;
USART2RX.buf[USART2RX.length]=ch;
USART2RX.length++;
if(ch=='\n')
{
USART2RX.rxCompleted=true;
USART2RX.buf[USART2RX.length-2]=0x00;
USART2->CR1^=USART_CR1_RXNEIE;
//実処理は、mainで行う。
}
}
/* USER CODE END USART2_IRQn 1 */
}
USART初期化(MX生成コード)
※最後のユーザーコードのところで、受信割り込み許可RXNEIEをSETする。
static void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
LL_USART_InitTypeDef USART_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART2);
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_2|LL_GPIO_PIN_3;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART2 interrupt Init */
NVIC_SetPriority(USART2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),1, 0));
NVIC_EnableIRQ(USART2_IRQn);
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
USART_InitStruct.BaudRate = 115200;
USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
USART_InitStruct.Parity = LL_USART_PARITY_NONE;
USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
LL_USART_Init(USART2, &USART_InitStruct);
LL_USART_ConfigAsyncMode(USART2);
LL_USART_Enable(USART2);
/* USER CODE BEGIN USART2_Init 2 */
LL_USART_EnableIT_RXNE(USART2);
/* USER CODE END USART2_Init 2 */
}
