外设接口

2 GPIO

2.1 读电平

LL库:

uint32_t LL_GPIO_IsInputPinSet(GPIO_TypeDef *GPIOx, uint32_t PinMask);

HAL库:

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

2.2 写电平

LL库:

void LL_GPIO_SetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask);
void LL_GPIO_ResetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask);

2.3 翻转电平

LL库:

void LL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint32_t PinMask); //翻转GPIO

2.4 复用JTAG IO为普通IO

LL库:

// todo
LL_GPIO_AF_Remap_SWJ_NOJTAG();

HAL库:

__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_AFIO_REMAP_SWJ_NOJTAG();

3 ADC

3.1 CubeMX配置详解

CubeMX默认配置图
javaw_I7t8h99PuJ.png
配置项:

  • ADCs_Common_Settings
    • Mode
      • Indenpendent Mode
  • ADC_Settings
    • Data Alignment。数据对齐功能,参考外设接口 > ADC数据对齐功能,通常选右对齐。
      • Left alignment
      • Right alignment
    • Scan Conversion Mode
      • Enabled
      • Disabled
    • Continuous Conversion Mode(连续转换模式、配置是启动自动连续转换还是单次转换)
      • Enabled、使能自动连续转换
      • Disabled、转换一次后停止需要手动控制才重新启动转换
    • Discontinuous Conversion Mode
      • Enabled
      • Disabled
  • ADC_Regular_ConversionMode
    • Enable Regular Conversions
    • Number Of Conversion
    • External Trigger Conversion Source

3.1.1 ADC数据对齐功能

3.2 LL库 无DMA

3.2.1 初始化

代码段 MX_ADCx_Init 中增加:

LL_ADC_Enable(ADCx);                       // 使能ADC 
LL_ADC_StartCalibration(ADCx);             // 校准ADC
while(LL_ADC_IsCalibrationOnGoing(ADCx));  // 等待ADC校准完成

3.2.2 读取ADC数值

uint16_t ADC_Value = 0;
LL_ADC_REG_SetSequencerRanks(ADCx, LL_ADC_REG_RANK_1, Channel);
LL_ADC_REG_StartConversionSWStart(ADCx);
while(!LL_ADC_IsActiveFlag_EOS(ADCx));
ADC_Value = LL_ADC_REG_ReadConversionData12(ADCx);

3.3 LL库 使用DMA

3.3.1 初始化

4 USART

4.1 初始化

CubeMx配置略。

LL库:

// 开启串口中断
LL_USART_ClearFlag_RXNE(USARTx);
LL_USART_EnableIT_RXNE(USARTx);

4.2 中断函数

4.3 重定向fputc和fgetc,启用printf和scanf

LL库:

static USART_TypeDef *target = NULL;

#ifdef __GNUC__
int __io_putchar(int ch)
{
	if(target == NULL)
		return EOF;
	while (LL_USART_IsActiveFlag_TC(target) == RESET);
	LL_USART_TransmitData8(target, (uint8_t) ch);
	return ch;
}
#else
int fputc(int ch, FILE *stream)
{
	if(target == NULL)
		return EOF;
	while(LL_USART_IsActiveFlag_TC(target) == RESET);
	LL_USART_TransmitData8(target, (uint8_t)ch);
	return ch;
}
#endif

HAL库:

static UART_HandleTypeDef *target = NULL;

/**
 * @brief: Initialize and select serial port as stdio source.
 * @param:
 * 		- UART_HandleTypeDef port: target port.
 */
void uart_stdio_init(UART_HandleTypeDef *port)
{
	target = port;
}

#ifdef __GNUC__
int __io_putchar(int ch)
{
	if(target == NULL)
		return EOF;
	HAL_UART_Transmit(target, (uint8_t *)&ch, 1, 0xFFFF);
	return ch;
}
#else
int fputc(int ch, FILE *stream)
{
	if(target == NULL)
		return EOF;
	HAL_UART_Transmit(target, (uint8_t *)&ch, 1, 0xFFFF);
	return ch;
}
#endif

#ifdef __GNUC__
int __io_getchar(void)
{
	uint8_t uart_rx_byte = 0;
	if(target == NULL)
		return EOF;
    HAL_UART_Receive(target, &uart_rx_byte, 1, HAL_MAX_DELAY);
    return uart_rx_byte;
}
#else
int fgetc(FILE *stream)
{
	uint8_t uart_rx_byte = 0;
	if(target == NULL)
		return EOF;
    HAL_UART_Receive(target, &uart_rx_byte, 1, HAL_MAX_DELAY);
    return uart_rx_byte;
}
#endif

随后需要注意若需要支持float数入输出,则需要如下操作:

  1. 右键工程 -> Properties 打开属性配置页
    Pasted image 20240422224456.png
  2. C/C++ Build -> Settings -> Tool Settings -> MCU Settings -> 打开printf或scanf输入输出float功能。
    stm32cubeide_3AosLnwUVi.png