NUCLEO-L432 usart串口驱动分享

作者: 轻音丶
上传时间为: 2017-09-08 08:48 AM
2017-09-08
阅读:

hello大家好,我又来了~ 因为最近工作忙,项目比较紧张,抽出时间来和大家分享一下关于l4的串口底层驱动。

针对于STM32系列单片机,本人是不推荐使用寄存器来进行开发的,开发的效率太低了。在ST官方可以看到一系列的STD标准库与HAL库,使用这一套标准,不仅刚接触该类单片机入手快,而且在ST的芯片与芯片的程序移植中非常吃香(从F1移植至F4库)。

本人是原本是偏爱STD库的,但是在接触F7的HAL库后(据我所知F7没有STD库),再使用STM32CubeMX工具,就对HAL无法自拔了!

终其原因如下:

1. 从F1开始一直覆盖至F7都有相对应的HAL库

2. HAL库所对应的串口、adc等各种句柄都非常简介明朗,配置起来甚至比STD库还要方便

3. STM32CubeMx可以直接生成代码

当然,令人迷恋的终究还是第三点。

废话说了一箩筐,咱们现在开始分享一下关于STM32L432的HAL库串口底层驱动方法,通过重定义绑定printf打印方法,来实现串口数据的输出。

首先打开STM32CubeMX工具,新建工程,选择STM32L432KC芯片。

进入工程之后,在Pinout中,使能串口2,同时在工具栏中打开Project项中的setting,如图

本人使用的开发工具是keil,版本号是5.21,所以在IDE选项中选择MDK-ARM V5,各位小伙伴选择相对应的环境就好,接着设置好项目名字(project name),项目位置(project location)即可。

接着在代码通用配置上(Code Generator),找到文件设置(Generated files),选中第一项,这样就可以独立生成对应的.c和.h文件了。这样咱们工程就配置好了,接着点击OK。

这是在工具栏上点击Project,下拉菜单选择Generate Code,等待进度条走完,提示Code success即可,如图

这样就可以直接打开项目工程了,保存在咱们刚刚在setting里面设定的位置(project location)里面。

打开工程后可以看到咱们新建立的工程目录非常清晰明朗,代码的条目也非常的清晰,简直太棒了

接下来咱们找到user目录,里面有main,gpio,usart等c和h文件,咱们现在要写的是串口底层,所以需要关注的是main文件和usart文件,现在打开main函数,可以看到里面已经将串口配置好了

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}

在main函数里面可以看到有用的这么几句话:

MX_GPIO_Init();

MX_USART2_UART_Init();

其他的关于时钟配置并不需要我们额外的关心,这时候咱们进入usart文件,可以观察一下串口的配置函数以及句柄

UART_HandleTypeDef huart2;

/* USART2 init function */

void MX_USART2_UART_Init(void)
{

  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_7B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(uartHandle->Instance==USART2)
  {
  /* USER CODE BEGIN USART2_MspInit 0 */

  /* USER CODE END USART2_MspInit 0 */
    /* USART2 clock enable */
    __HAL_RCC_USART2_CLK_ENABLE();
  
    /**USART2 GPIO Configuration    
    PA2     ------> USART2_TX
    PA3     ------> USART2_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN USART2_MspInit 1 */

  /* USER CODE END USART2_MspInit 1 */
  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

  if(uartHandle->Instance==USART2)
  {
  /* USER CODE BEGIN USART2_MspDeInit 0 */

  /* USER CODE END USART2_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART2_CLK_DISABLE();
  
    /**USART2 GPIO Configuration    
    PA2     ------> USART2_TX
    PA3     ------> USART2_RX 
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);

  /* USER CODE BEGIN USART2_MspDeInit 1 */

  /* USER CODE END USART2_MspDeInit 1 */
  }
} 
需要关注的有三个函数:

1. MX_USART2_UART_Init ()

2. HAL_UART_MspInit ()

3. HAL_UART_MspDeInit ()

第一个函数为串口初始化函数,调用这个函数即可完成串口的通用配置,第二个函数为串口的底层初始化,主要是gpio的配置,第三个函数为串口的重复位,主要是禁用时钟和引脚的重新复位。第三个函数基本用不到,咱们只需用到前两个函数即可完成串口的调配。

从代码上可以看到,咱们串口的波特率是115200,包括停止位,起始位以及校验位都已经配置好了,就缺一个写函数了,这时候咱们找一个串口写函数来~~~

void uart_write (USART_TypeDef *uart, uint8_t ch) {
	while((uart->ISR&0X40)==0);
	uart->TDR=ch;   
}
好的,现在咱们有初始化配置函数以及写函数,接下来咱们重定义一下printf的输出函数就好啦。
int fputc (int ch, FILE *f) {
	uart_write (USART2, ch);
	return ch;
}	
这样咱们关于串口的所有配置就好了,接下来咱们写好main函数,就可以使用串口自由的打印数据了。
void delay_ms () {
	uint32_t val = 0x1FFF;
	
	while (val--);
}

int main(void)
{
	HAL_Init();

	SystemClock_Config();

	MX_GPIO_Init();
	MX_USART2_UART_Init();

	while (1)
	{
		printf ("Hello world \r\n");
		delay_ms ();
	}
}
把没用的注释都删了,保留有用的代码,在自写一个延时函数,咱们的代码部分就全部完成了,接下来就是令人兴奋的试验阶段了

按F7将代码编译,然后按F8将代码骚录进去,打开串口调试助手,可以看到咱们想要的数据就来了

作者其它经验
全部评论 ()
条评论
写评论

创建讨论帖子

登录 后参与评论
系统提示