• STM32F4VGT6-DISCOVERY:uart1驱动


    对于这款板子,官方并没有提供串口例程,只能自行添加。

    一、PA9/PA10复用成串口1功能不可用

    驱动测试代码如下:

    main.c:

    1. #include "main.h"
    2. #include
    3. void usart1_init(void)
    4. {
    5. GPIO_InitTypeDef GPIO_InitStructure;
    6. USART_InitTypeDef USART_InitStructure;
    7. NVIC_InitTypeDef NVIC_InitStructure;
    8. //(1)串口时钟和 GPIO 时钟使能
    9. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//GPIO口时钟使能, 引脚PA9,PA10可以复用为串口功能
    10. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口UART1时钟使能, 串口1是挂载在 APB2总线下的外设
    11. //(2)配置GPIO引脚为复用功能[PA9+PA10]
    12. GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
    13. GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
    14. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
    15. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    16. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//电平翻转速度100MHz
    17. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽复用输出
    18. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    19. GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化 PA9,PA10
    20. //(3)配置串口1参数
    21. USART_InitStructure.USART_BaudRate = 115200;//波特率
    22. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不使用硬件流控制
    23. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式
    24. USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
    25. USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
    26. USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8个数据位
    27. USART_Init(USART1, &USART_InitStructure); //初始化串口1
    28. //(4) 开启中断并且初始化 NVIC,使能相应中断[接收一个byte触发中断一次]
    29. USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    30. NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    31. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级 3
    32. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//响应优先级 3
    33. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    34. NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器
    35. //(5) 使能串口1
    36. USART_Cmd(USART1, ENABLE);
    37. }
    38. //串口1中断服务函数
    39. void USART1_IRQHandler(void)
    40. {
    41. char res;
    42. //检查标志位
    43. if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    44. {
    45. res = USART_ReceiveData(USART1);//收到数据后读出来
    46. USART_SendData(USART1,res);//读到数据后立刻发送出去
    47. //清空标志位
    48. USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    49. }
    50. }
    51. int main(void)
    52. {
    53. usart1_init();
    54. while(1)
    55. {
    56. ;
    57. }
    58. return 0;
    59. }

    固件烧录后,连接PC端串口工具,串口收发功能不可用。原因:PA9/PA10设计给板载USB使用,打开原理如下:

    所以,只能换一组GPIO,换成PB6/PB7(原理图上可确认没有其他外设使用),测试代码如下:

    1. #if 0
    2. void usart1_init(void)
    3. {
    4. GPIO_InitTypeDef GPIO_InitStructure;
    5. USART_InitTypeDef USART_InitStructure;
    6. NVIC_InitTypeDef NVIC_InitStructure;
    7. //(1)串口时钟和 GPIO 时钟使能
    8. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//GPIO口时钟使能, 引脚PA9,PA10可以复用为串口功能
    9. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口UART1时钟使能, 串口1是挂载在 APB2总线下的外设
    10. //(2)配置GPIO引脚为复用功能[PA9+PA10]
    11. GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
    12. GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
    13. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
    14. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    15. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//电平翻转速度100MHz
    16. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽复用输出
    17. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    18. GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化 PA9,PA10
    19. //(3)配置串口1参数
    20. USART_InitStructure.USART_BaudRate = 115200;//波特率
    21. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不使用硬件流控制
    22. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式
    23. USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
    24. USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
    25. USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8个数据位
    26. USART_Init(USART1, &USART_InitStructure); //初始化串口1
    27. //(4) 开启中断并且初始化 NVIC,使能相应中断[接收一个byte触发中断一次]
    28. USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    29. NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    30. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级 3
    31. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//响应优先级 3
    32. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    33. NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器
    34. //(5) 使能串口1
    35. USART_Cmd(USART1, ENABLE);
    36. }
    37. //串口1中断服务函数
    38. void USART1_IRQHandler(void)
    39. {
    40. char res;
    41. //检查标志位
    42. if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    43. {
    44. res = USART_ReceiveData(USART1);//收到数据后读出来
    45. USART_SendData(USART1,res);//读到数据后立刻发送出去
    46. //清空标志位
    47. USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    48. }
    49. }
    50. #else
    51. void usart1_init(void)
    52. {
    53. GPIO_InitTypeDef GPIO_InitStructure;
    54. USART_InitTypeDef USART_InitStructure;
    55. NVIC_InitTypeDef NVIC_InitStructure;
    56. //(1)串口时钟和 GPIO 时钟使能
    57. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); //使能GPIOB时钟
    58. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口UART1时钟使能, 串口1是挂载在 APB2总线下的外设
    59. //(2)配置GPIO引脚为复用功能[PB6+PB7]
    60. GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
    61. GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);
    62. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
    63. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    64. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//电平翻转速度100MHz
    65. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽复用输出
    66. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    67. GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化 PA9,PA10
    68. //(3)配置串口1参数
    69. USART_InitStructure.USART_BaudRate = 115200;//波特率
    70. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不使用硬件流控制
    71. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式
    72. USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
    73. USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
    74. USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8个数据位
    75. USART_Init(USART1, &USART_InitStructure); //初始化串口1
    76. //(4) 开启中断并且初始化 NVIC,使能相应中断[接收一个byte触发中断一次]
    77. USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    78. NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    79. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级 3
    80. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//响应优先级 3
    81. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    82. NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器
    83. //(5) 使能串口1
    84. USART_Cmd(USART1, ENABLE);
    85. }
    86. //串口1中断服务函数
    87. void USART1_IRQHandler(void)
    88. {
    89. char res;
    90. STM_EVAL_LEDOn(LED4);
    91. //检查标志位
    92. if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    93. {
    94. res = USART_ReceiveData(USART1);//收到数据后读出来
    95. STM_EVAL_LEDOn(LED5);
    96. USART_SendData(USART1,res);//读到数据后立刻发送出去
    97. //清空标志位
    98. USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    99. }
    100. }
    101. #endif
    102. int main(void)
    103. {
    104. usart1_init();
    105. while(1)
    106. {
    107. ;
    108. }
    109. return 0;
    110. }

    板子实物图连接如下:

    串口工具测试如下:

    二、串口标准输入输出重定向打印实现

    直接重写标准输入输出函数的底层接口即可,如下:

    //重写printf底层函数接口

    int fputc(int c, FILE *stream)

    {

      USART1->DR=c; //发送一个字符

      while(!(USART1->SR&1<<7)){}

    return c;

    }

    //重写scanf底层函数接口

    int fgetc(FILE *stream)

    {

      while(!(USART1->SR&1<<5)){}

        return USART1->DR;

    }

    烧录固件,并按reset键,观察串口调试助手上的打印:使用ST-LINK的方式进行烧录

    串口助手:

    三、完整代码

    usart.c

    1. /* Includes ------------------------------------------------------------------*/
    2. #include "stm32f4xx.h"
    3. #include
    4. void usart1_init(uint32_t BaudRate)
    5. {
    6. GPIO_InitTypeDef GPIO_InitStructure;
    7. USART_InitTypeDef USART_InitStructure;
    8. NVIC_InitTypeDef NVIC_InitStructure;
    9. //(1)串口时钟和 GPIO 时钟使能
    10. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); //使能GPIOB时钟
    11. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口UART1时钟使能, 串口1是挂载在 APB2总线下的外设
    12. //(2)配置GPIO引脚为复用功能[PB6+PB7]
    13. GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
    14. GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);
    15. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
    16. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    17. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//电平翻转速度100MHz
    18. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽复用输出
    19. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    20. GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化 PA9,PA10
    21. //(3)配置串口1参数
    22. USART_InitStructure.USART_BaudRate = BaudRate;//波特率
    23. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不使用硬件流控制
    24. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式
    25. USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
    26. USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
    27. USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8个数据位
    28. USART_Init(USART1, &USART_InitStructure); //初始化串口1
    29. //(4) 开启中断并且初始化 NVIC,使能相应中断[接收一个byte触发中断一次]
    30. USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    31. NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    32. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级 3
    33. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//响应优先级 3
    34. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    35. NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器
    36. //(5) 使能串口1
    37. USART_Cmd(USART1, ENABLE);
    38. }
    39. //串口1中断服务函数
    40. void USART1_IRQHandler(void)
    41. {
    42. char res;
    43. //检查标志位
    44. if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    45. {
    46. res = USART_ReceiveData(USART1);//收到数据后读出来
    47. USART_SendData(USART1,res);//读到数据后立刻发送出去
    48. //清空标志位
    49. USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    50. }
    51. }
    52. //重写printf底层函数接口
    53. int fputc(int c, FILE *stream)
    54. {
    55. USART1->DR=c; //发送一个字符
    56. while(!(USART1->SR&1<<7)){}
    57. return c;
    58. }
    59. //重写scanf底层函数接口
    60. int fgetc(FILE *stream)
    61. {
    62. while(!(USART1->SR&1<<5)){}
    63. return USART1->DR;
    64. }
    65. /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

    usart.h

    1. #ifndef __USART__H__
    2. #define __USART__H__
    3. void usart1_init(uint32_t BaudRate);
    4. #endif /* __USART__H__ */

    main.c

    1. #include "usart.h"
    2. #include
    3. int main(void)
    4. {
    5. usart1_init(115200);
    6. printf("hello world!\n");
    7. while(1)
    8. {
    9. ;
    10. }
    11. return 0;
    12. }

    注:这款Discovery开发板是基于标准外设库函数来开发的,因此工程中要把串口相关的库函数文件添加进来,如下:

  • 相关阅读:
    ModStartCMS v5.1.0 数据采集接口,登录自动注册
    【计算机网络】网络编程接口 Socket API 解读(8)
    计算机毕业设计 无人智慧超市管理系统的设计与实现 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试
    C# - 反射动态添加/删除Attribute特性
    Outside ExpertPDF HtmlToPdf 转换器 17.0
    EN 14342木地板产品—CE认证
    Java并发编程学习二:线程安全
    系统开发视角下的诊断 ———— 车身控制(B)诊断故障
    【图神经网络论文整理】(八)—— Heterogeneous Graph Attention Network:HAN
    Android音视频开发系列:手撕FFmpeg音视频编解码
  • 原文地址:https://blog.csdn.net/qq_40088639/article/details/134045644