ST MCU Finder
安装免费手机应用,
寻找理想的ST MCU

[STM32F4] STM32F4串口4标准库程序的问题

[复制链接]
858|22
 楼主 | 2019-12-7 15:45 | 显示全部楼层 |阅读模式
有一个板子,STM32F407VET6,串口4接在PC10和PC11上。
2.jpg
我用标准库写了个程序,通讯不上。
初始化代码如下:

//³õʼ»¯IO ´®¿Ú4
//bound:²¨ÌØÂÊ
void uart_init(u32 bound){
   //GPIO¶Ë¿ÚÉèÖÃ
  GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
       
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); //ʹÄÜGPIOCʱÖÓ
        RCC_APB2PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);//ʹÄÜUART4ʱÖÓ

        //´®¿Ú1¶ÔÓ¦Òý½Å¸´ÓÃÓ³Éä
        GPIO_PinAFConfig(GPIOC,GPIO_PinSource10,GPIO_AF_UART4); //GPIOC10¸´ÓÃΪUART4
        GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_UART4); //GPIOC11¸´ÓÃΪUART4
       
        //USART1¶Ë¿ÚÅäÖÃ
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_10; //GPIOC11ÓëGPIOC10
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//¸´Óù¦ÄÜ
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //ËÙ¶È50MHz
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //ÍÆÍ츴ÓÃÊä³ö
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //ÉÏÀ­
        GPIO_Init(GPIOC,&GPIO_InitStructure); //³õʼ»¯PC11£¬PC10

   //USART1 ³õʼ»¯ÉèÖÃ
        USART_InitStructure.USART_BaudRate = bound;//²¨ÌØÂÊÉèÖÃ
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;//×Ö³¤Îª8λÊý¾Ý¸ñʽ
        USART_InitStructure.USART_StopBits = USART_StopBits_1;//Ò»¸öֹͣλ
        USART_InitStructure.USART_Parity = USART_Parity_No;//ÎÞÆæżУÑéλ
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//ÎÞÓ²¼þÊý¾ÝÁ÷¿ØÖÆ
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //ÊÕ·¢Ä£Ê½
  USART_Init(UART4, &USART_InitStructure); //³õʼ»¯´®¿Ú1
       
  USART_Cmd(UART4, ENABLE);  //ʹÄÜ´®¿Ú1
       
        USART_ClearFlag(UART4, USART_FLAG_TC);
       
//#if EN_USART1_RX       
//        USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);//¿ªÆôÏà¹ØÖжÏ

//        //Usart1 NVIC ÅäÖÃ
//  NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;//´®¿Ú1ÖжÏͨµÀ
//        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//ÇÀÕ¼ÓÅÏȼ¶3
//        NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;                //×ÓÓÅÏȼ¶3
//        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQͨµÀʹÄÜ
//        NVIC_Init(&NVIC_InitStructure);        //¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷¡¢

//#endif
       
}
开始我用中断,不行,后来又改成查询,都不行。

中断程序:
void UART4_IRQHandler(void)                        //´®¿Ú1ÖжϷþÎñ³ÌÐò
{
        u8 Res;
#if SYSTEM_SUPPORT_OS                 //Èç¹ûSYSTEM_SUPPORT_OSΪÕ棬ÔòÐèÒªÖ§³ÖOS.
        OSIntEnter();   
#endif
        if(USART_GetITStatus(UART4, USART_IT_RXNE) != RESET)  //½ÓÊÕÖжÏ(½ÓÊÕµ½µÄÊý¾Ý±ØÐëÊÇ0x0d 0x0a½áβ)
        {
                Res =USART_ReceiveData(UART4);//(UART4->DR);        //¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ý
               
               
                if((USART_RX_STA&0x8000)==0)//½ÓÊÕδÍê³É
                {
                        if(USART_RX_STA&0x4000)//½ÓÊÕµ½ÁË0x0d
                        {
                                if(Res!=0x0a)USART_RX_STA=0;//½ÓÊÕ´íÎó,ÖØпªÊ¼
                                else USART_RX_STA|=0x8000;        //½ÓÊÕÍê³ÉÁË
                        }
                        else //»¹Ã»ÊÕµ½0X0D
                        {       
                                if(Res==0x0d)USART_RX_STA|=0x4000;
                                else
                                {
                                        USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
                                        USART_RX_STA++;
                                        if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//½ÓÊÕÊý¾Ý´íÎó,ÖØпªÊ¼½ÓÊÕ          
                                }                 
                        }
                }                    
  }
#if SYSTEM_SUPPORT_OS         //Èç¹ûSYSTEM_SUPPORT_OSΪÕ棬ÔòÐèÒªÖ§³ÖOS.
        OSIntExit();                                                                                           
#endif
}

查询代码:
while (USART_GetFlagStatus(UART4, USART_FLAG_RXNE) == RESET);
                data=USART_ReceiveData(UART4);

请大神看看,如何修改代码?谢谢!

使用特权

评论回复
| 2019-12-7 15:56 | 显示全部楼层
本帖最后由 sky.sun.zz 于 2019-12-7 16:03 编辑

F407的UART4默认IO口是PA0和PA1,需要重复用功能重映射函数。
GPIO_PinRemapConfig()

另外UART与USART有所不同,F407的UART4并非USART4。楼主应该仔细阅读ST官方使用说明书。

无标题.png



使用特权

评论回复
 楼主 | 2019-12-7 16:06 | 显示全部楼层
sky.sun.zz 发表于 2019-12-7 15:56
F407的UART4默认IO口是PA0和PA1,需要重复用功能重映射函数。
GPIO_PinRemapConfig()

谢谢!怎么用啊?我不会用这个函数。还请明示。
我在百度上搜到的一些用法,还是不知道怎么写。
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);

使用特权

评论回复
 楼主 | 2019-12-7 16:12 | 显示全部楼层
我在stm32f4xx_gpio.h里没找到这个函数。不知道在哪里。

另外我用的标准库,有些地方改成了UART4。是不是USART的地方都要改成UART呀?谢谢

使用特权

评论回复
| 2019-12-7 16:29 | 显示全部楼层
是的 USART 和 UART 是不一样的 !一个是同步 一个是非同步的意思吧!

使用特权

评论回复
 楼主 | 2019-12-7 16:32 | 显示全部楼层
goodluck09876 发表于 2019-12-7 16:29
是的 USART 和 UART 是不一样的 !一个是同步 一个是非同步的意思吧!

谢谢!
typedef struct
{
  uint32_t USART_BaudRate;            /*!< This member configures the USART communication baud rate.
                                           The baud rate is computed using the following formula:
                                            - IntegerDivider = ((PCLKx) / (8 * (OVR8+1) * (USART_InitStruct->USART_BaudRate)))
                                            - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 8 * (OVR8+1)) + 0.5
                                           Where OVR8 is the "oversampling by 8 mode" configuration bit in the CR1 register. */

  uint16_t USART_WordLength;          /*!< Specifies the number of data bits transmitted or received in a frame.
                                           This parameter can be a value of @ref USART_Word_Length */

  uint16_t USART_StopBits;            /*!< Specifies the number of stop bits transmitted.
                                           This parameter can be a value of @ref USART_Stop_Bits */

  uint16_t USART_Parity;              /*!< Specifies the parity mode.
                                           This parameter can be a value of @ref USART_Parity
                                           @NOTE When parity is enabled, the computed parity is inserted
                                                 at the MSB position of the transmitted data (9th bit when
                                                 the word length is set to 9 data bits; 8th bit when the
                                                 word length is set to 8 data bits). */

  uint16_t USART_Mode;                /*!< Specifies wether the Receive or Transmit mode is enabled or disabled.
                                           This parameter can be a value of @ref USART_Mode */

  uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled
                                           or disabled.
                                           This parameter can be a value of @ref USART_Hardware_Flow_Control */
} USART_InitTypeDef;
我找到这个结构体,在那个文件里搜UART,找不到。可怎么办呀?

使用特权

评论回复
 楼主 | 2019-12-7 16:38 | 显示全部楼层
sky.sun.zz 发表于 2019-12-7 15:56
F407的UART4默认IO口是PA0和PA1,需要重复用功能重映射函数。
GPIO_PinRemapConfig()

GPIO_PinAFConfig(GPIOC,GPIO_PinSource10,GPIO_AF_UART4); //GPIOC10¸´ÓÃΪUART4
        GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_UART4); //GPIOC11¸´ÓÃΪUART4
我有这两句,应该可以了吧。
函数说明:
/**
  * @brief  Changes the mapping of the specified pin.
  * @param  GPIOx: where x can be (A..K) to select the GPIO peripheral for STM32F405xx/407xx and STM32F415xx/417xx devices
  *                      x can be (A..I) to select the GPIO peripheral for STM32F42xxx/43xxx devices.
  *                      x can be (A, B, C, D and H) to select the GPIO peripheral for STM32F401xx devices.
  * @param  GPIO_PinSource: specifies the pin for the Alternate function.
  *         This parameter can be GPIO_PinSourcex where x can be (0..15).
  * @param  GPIO_AFSelection: selects the pin to used as Alternate function.
  *          This parameter can be one of the following values:
  *            @ARG GPIO_AF_RTC_50Hz: Connect RTC_50Hz pin to AF0 (default after reset)
  *            @arg GPIO_AF_MCO: Connect MCO pin (MCO1 and MCO2) to AF0 (default after reset)
  *            @arg GPIO_AF_TAMPER: Connect TAMPER pins (TAMPER_1 and TAMPER_2) to AF0 (default after reset)
  *            @arg GPIO_AF_SWJ: Connect SWJ pins (SWD and JTAG)to AF0 (default after reset)
  *            @arg GPIO_AF_TRACE: Connect TRACE pins to AF0 (default after reset)
  *            @arg GPIO_AF_TIM1: Connect TIM1 pins to AF1
  *            @arg GPIO_AF_TIM2: Connect TIM2 pins to AF1
  *            @arg GPIO_AF_TIM3: Connect TIM3 pins to AF2
  *            @arg GPIO_AF_TIM4: Connect TIM4 pins to AF2
  *            @arg GPIO_AF_TIM5: Connect TIM5 pins to AF2
  *            @arg GPIO_AF_TIM8: Connect TIM8 pins to AF3
  *            @arg GPIO_AF_TIM9: Connect TIM9 pins to AF3
  *            @arg GPIO_AF_TIM10: Connect TIM10 pins to AF3
  *            @arg GPIO_AF_TIM11: Connect TIM11 pins to AF3
  *            @arg GPIO_AF_I2C1: Connect I2C1 pins to AF4
  *            @arg GPIO_AF_I2C2: Connect I2C2 pins to AF4
  *            @arg GPIO_AF_I2C3: Connect I2C3 pins to AF4
  *            @arg GPIO_AF_SPI1: Connect SPI1 pins to AF5
  *            @arg GPIO_AF_SPI2: Connect SPI2/I2S2 pins to AF5
  *            @arg GPIO_AF_SPI4: Connect SPI4 pins to AF5
  *            @arg GPIO_AF_SPI5: Connect SPI5 pins to AF5
  *            @arg GPIO_AF_SPI6: Connect SPI6 pins to AF5
  *            @arg GPIO_AF_SAI1: Connect SAI1 pins to AF6 for STM32F42xxx/43xxx devices.      
  *            @arg GPIO_AF_SPI3: Connect SPI3/I2S3 pins to AF6
  *            @arg GPIO_AF_I2S3ext: Connect I2S3ext pins to AF7
  *            @arg GPIO_AF_USART1: Connect USART1 pins to AF7
  *            @arg GPIO_AF_USART2: Connect USART2 pins to AF7
  *            @arg GPIO_AF_USART3: Connect USART3 pins to AF7
  *            @arg GPIO_AF_UART4: Connect UART4 pins to AF8
  *            @arg GPIO_AF_UART5: Connect UART5 pins to AF8
  *            @arg GPIO_AF_USART6: Connect USART6 pins to AF8
  *            @arg GPIO_AF_UART7: Connect UART7 pins to AF8
  *            @arg GPIO_AF_UART8: Connect UART8 pins to AF8
  *            @arg GPIO_AF_CAN1: Connect CAN1 pins to AF9
  *            @arg GPIO_AF_CAN2: Connect CAN2 pins to AF9
  *            @arg GPIO_AF_TIM12: Connect TIM12 pins to AF9
  *            @arg GPIO_AF_TIM13: Connect TIM13 pins to AF9
  *            @arg GPIO_AF_TIM14: Connect TIM14 pins to AF9
  *            @arg GPIO_AF_OTG_FS: Connect OTG_FS pins to AF10
  *            @arg GPIO_AF_OTG_HS: Connect OTG_HS pins to AF10
  *            @arg GPIO_AF_ETH: Connect ETHERNET pins to AF11
  *            @arg GPIO_AF_FSMC: Connect FSMC pins to AF12
  *            @arg GPIO_AF_FMC: Connect FMC pins to AF12 for STM32F42xxx/43xxx devices.   
  *            @arg GPIO_AF_OTG_HS_FS: Connect OTG HS (configured in FS) pins to AF12
  *            @arg GPIO_AF_SDIO: Connect SDIO pins to AF12
  *            @arg GPIO_AF_DCMI: Connect DCMI pins to AF13
  *            @arg GPIO_AF_LTDC: Connect LTDC pins to AF14 for STM32F429xx/439xx devices.
  *            @arg GPIO_AF_EVENTOUT: Connect EVENTOUT pins to AF15
  * @retval None
  */
void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)
{
  uint32_t temp = 0x00;
  uint32_t temp_2 = 0x00;
  
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));
  assert_param(IS_GPIO_AF(GPIO_AF));
  
  temp = ((uint32_t)(GPIO_AF) << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)) ;
  GPIOx->AFR[GPIO_PinSource >> 0x03] &= ~((uint32_t)0xF << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)) ;
  temp_2 = GPIOx->AFR[GPIO_PinSource >> 0x03] | temp;
  GPIOx->AFR[GPIO_PinSource >> 0x03] = temp_2;
}

使用特权

评论回复
| 2019-12-7 16:41 | 显示全部楼层
Cjy_JDxy 发表于 2019-12-7 16:06
谢谢!怎么用啊?我不会用这个函数。还请明示。
我在百度上搜到的一些用法,还是不知道怎么写。
GPIO_Pin ...



无标题.png

使用特权

评论回复
 楼主 | 2019-12-7 16:46 | 显示全部楼层

谢谢!
GPIO_PinAFConfig(GPIOC,GPIO_PinSource10,GPIO_AF_UART4); //GPIOC10¸´ÓÃΪUART4
        GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_UART4); //GPIOC11¸´ÓÃΪUART4
我有这两句。你帮我看看,搞好了我给你打赏。
我1楼和7楼都有这两句。
应该是重定向的吧。

使用特权

评论回复
| 2019-12-7 16:46 | 显示全部楼层
Cjy_JDxy 发表于 2019-12-7 16:38
GPIO_PinAFConfig(GPIOC,GPIO_PinSource10,GPIO_AF_UART4); //GPIOC10¸´ÓÃΪUART4
        GPIO_PinAFConf ...

UART不是那么好玩的,楼主还是先玩USART吧,

使用特权

评论回复
 楼主 | 2019-12-7 16:49 | 显示全部楼层
sky.sun.zz 发表于 2019-12-7 16:46
UART不是那么好玩的,楼主还是先玩USART吧,

不是啊。我不是玩,硬件设计了那个口上了,那个家伙乱改口,我本来弄到串口1,它非弄到串口4.
还得重定向,我恨死他了

使用特权

评论回复
| 2019-12-7 16:49 | 显示全部楼层
本帖最后由 sky.sun.zz 于 2019-12-7 16:51 编辑
Cjy_JDxy 发表于 2019-12-7 16:46
谢谢!
GPIO_PinAFConfig(GPIOC,GPIO_PinSource10,GPIO_AF_UART4); //GPIOC10¸´ÓÃΪUART4
         ...

那2句应该是对的,但是UART通行要求通讯的对方也是UART,同步方式要设置的寄存器不少,我也没玩过,还是先玩USART吧!楼主在初始化函数中设置UART4为USART4,F407不认识呀。

使用特权

评论回复
 楼主 | 2019-12-7 16:51 | 显示全部楼层
sky.sun.zz 发表于 2019-12-7 16:49
那2句应该是对的,但是UART通行要求通讯的对方也是UART,同步方式要设置的寄存器不少,我也没玩过,还是 ...

好吧。谢谢

使用特权

评论回复
 楼主 | 2019-12-7 17:43 | 显示全部楼层
搞好了,结帖。
RCC_APB2PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);//ʹÄÜUART4ʱÖÓ
这一句错了。改成
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);//ʹÄÜUART4ʱÖÓ
这样就好啦。哈哈

使用特权

评论回复
| 2019-12-7 21:58 | 显示全部楼层
666666

使用特权

评论回复
| 2019-12-8 18:37 | 显示全部楼层
Cjy_JDxy 发表于 2019-12-7 17:43
搞好了,结帖。
RCC_APB2PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);//ʹÄÜUART4ʱÖÓ
这一句错 ...

都是粗心惹得祸

使用特权

评论回复
| 2019-12-8 22:48 | 显示全部楼层
就喜欢看这样的结贴,自己记下一点东西。

使用特权

评论回复
| 2019-12-9 15:20 | 显示全部楼层
本帖最后由 13543016677 于 2019-12-9 15:55 编辑

不好意思, 看到你贴的代码, 一望无际的标准库, 太高(啰)大(嗦)了.
来踢个馆, 大家互相学习, 哈~~
以前我也标准库, 码字贼快, 一天码十页八页.
但调试时...., 死扑街, 这是哪个写的, 这里这里还有这里, 什么意思, 有毛关联, ......嗯, 好像 , 嗯, 前天晚上写的~~后来痛下决心, 项目都寄存器, 凡有库的, 强逼症发作, 一行行的杀掉,   调试时思路简单了, 头发也密了!!
贴几行现在工作的UART代码段,  有效代码20行才左右, 完成 引脚+USART+优先级, 哪里出错, 查来查去就这几行, 快!



void vUsart_Init()  {
    float T;
    u16  M,F;  
   
    // 使能GPIO时钟, 宏定义, 方便代码复用
    USART_CLOCK_CMD;     
   
    // GPIO初始化,  一行搞定: 端口+PIN+输出类型+上下拉+功能复用,  比原子哥的函数更爽
    GPIOSet (USART_TX_GPIOx , USART_TX_PINx ,  MODE_AF , OTYPE_PP , OSPEED_50M , PUPD_UP , USART_AFx ); // TX
    GPIOSet (USART_RX_GPIOx , USART_RX_PINx ,  MODE_AF , OTYPE_PP , OSPEED_50M  _PUPD_UP, USART_AFx ); // RX
   
    // USART初始化     115200-8-N-1
    T=(float)(USART_CLK *1000000)/(USART_BRR *16); // 得到USARTDIV,OVER8设置为0
    M=T;                                     // 得到整数部分
    F=(T-M)*16;                           // 得到小数部分,OVER8设置为0, *16=左移4位         
    M<<=4;
    M=M+F;  
    USARTx ->BRR = M;                // 设置波特率因子  

    USARTx ->CR1  = 0;                // 清0     
    USARTx ->CR1 |= 0<<2;         // 接收                   
    USARTx ->CR1 |= 1<<3;         // 发送
    USARTx ->CR1 |= 0<<10;       // 校验
    USARTx ->CR1 |= 0<<12;       // 字长      
    USARTx ->CR1 |= 1<<13;       // 使能       
    NVICSet( USARTx_IQRn, 3);     // 优先级设置, 也是自己改的函数, 全局组4, 16级抢占, 0级优先, 简单清晰
}







使用特权

评论回复

评论

icecut 2019-12-9 23:24 回复TA
代码不是为了查错而存在. lz也不是因为代码复杂而错误 
 楼主 | 2019-12-9 16:37 | 显示全部楼层
13543016677 发表于 2019-12-9 15:20
不好意思, 看到你贴的代码, 一望无际的标准库, 太高(啰)大(嗦)了.
来踢个馆, 大家互相学习, 哈~~
以前我也 ...

你这也挺好。可是还有人用HAL库呢!
看个人爱好

使用特权

评论回复
| 2019-12-9 23:26 | 显示全部楼层
Cjy_JDxy 发表于 2019-12-9 16:37
你这也挺好。可是还有人用HAL库呢!
看个人爱好

hal库, 不是用库, 而是自动生成代码.

你只需要告诉cubemx你用那个腿. 什么功能, 代码是自动生成的.你这种粗心错误,就不会出现了.当然软件有时候也有bug, 大部分人遇不到.

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表