STM32
直播中

张娟

7年用户 2119经验值
私信 关注
[问答]

请问STM32F429里的UART怎么使用?

请问STM32F429里的UART怎么使用?

回帖(1)

h1654155275.5741

2021-10-22 16:23:42
#if 1
/// 重定向c库函数printf到USART1
int fputc(int ch, FILE *f)
{
        /* 发送一个字节数据到USART1 */
        USART_SendData(USART1, (uint8_t) ch);
        
        /* 等待发送完毿*/
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);        
   
        return (ch);
}


/// 重定向c库函数scanf到USART1
int fgetc(FILE *f)
{
        /* 等待串口1输入数据 */
        while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);


        return (int)USART_ReceiveData(USART1);
}
#endif
/*********************************************END OF FILE**********************/



USART 只需两根信号线即可完成双向通信,对硬件要求低,使得很多模块都预留USART 接口来实现与其他模块或者控制器进行数据传输,比如 GSM 模块, WIFI 模块、蓝牙模块

  

APB2(最高 90MHz)                                    APB1(最高 45MHz)






USART1USART6USART2USART3UART4UART5UART7UART8
TXPA9/PB6PC6/PG14PA2/PD5PB10/PD8
/PC10
PA0/PC10PC12PF7/PE8PE1
RXPA10/PB7PC7/PG9PA3/PD6PB11/PD9
/PC11
PA1/PC11PD2PF6/PE7PE0
SCLKPA8PG7/PC8PA4/PD7PB12/PD10
/PC12




nCTSPA11PG13/PG15PA0/PD3PB13/PD11



nRTSPA12PG8/PG12PA1/PD4PB14/PD12



串口1收发数据配置
  配合原子的 usmart可以方便的进行调试,使用usmart可以通过串口调用函数,可以传参数非常方便。
void NVIC_Configuration_1(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;
        /* 配置 NVIC 为优先级绿1 */
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        /* 配置中断源:按键 1 */
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
        /* 配置抢占优先级: 1 */
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
        /* 配置子优先级_1 */
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
        /* 使能中断通道 */
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
}

void USART1_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
       
        /* config USART1 clock */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
       
        /* USART1 GPIO config */
        /* Configure USART1 Tx (PA.09) as alternate function push-pull */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);   
       
        /* Configure USART1 Rx (PA.10) as input floating */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        /* USART1 mode config */
        USART_InitStructure.USART_BaudRate = 115200;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        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(USART1, &USART_InitStructure);
        NVIC_Configuration_1();
        USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
        USART_Cmd(USART1, DISABLE);
        (void)USART1->SR; (void)USART1->DR;
        USART_ClearFlag(USART1, USART_FLAG_TC);
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
        USART_Cmd(USART1, ENABLE);

}



void USART1_IRQHandler_FUN(void)
{

        u8 data;

        (void)USART1->SR;   //Error clear;
        data =        (u8)(USART1->DR & (u16)0x01FF);
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
        resevice_buf(data);//
        get_buf_usart1[get_usart1_i] = data;
        USART_SendData(USART1, data);       
        get_usart1_i++;
        if(get_buf_usart1[0] != 0xFF)
        {
                get_usart1_i=0;
        }
               
        if(get_usart1_i==4)
        {       
                AnalizingBuf2();
                get_usart1_i = 0;
                gRxHostBufferFlush(4,get_buf_usart1);
        }
       
}
/// 重定向c库函数printf到USART1
int fputc(int ch, FILE *f)
{
                /* 发送一个字节数据到USART1 */
                USART_SendData(USART1, (uint8_t) ch);
               
                /* 等待发送完毿*/
                while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);               
       
                return (ch);
}

/// 重定向c库函数scanf到USART1
int fgetc(FILE *f)
{
                /* 等待串口1输入数据 */
                while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

                return (int)USART_ReceiveData(USART1);
}
使用USART1进行串口调试,打印信息到电脑
  程序是如何找到中断服务程序呢?在启动文件startup_stm32f10x_md.s中有这样一段代码,汇编DCD USART1_IRQHandler
  
  

  

   
  stm32串口调试是一个很好的方法
  一般有4个上的串口,可以将printf函数重定向到一个UART。这样就可以用printf函数将单片机的数据打印到PC上的超级终端或串口调试助手。
  可以通过串口发送一些参数方便调试,可以用一个协议易于操作
   
  //定义一个协议,关于数据收发的
//第一位:判断数据是否正确
//第二位:判断数据是否正确
//第三位:存放参数多少
//第四位:参数[1]
//第五位:参数[2]
//第n位:参数[n]
/*
Buffur_Full接受完毕标志位,意思可以解析程序了
*/

char get_From_PC[64];
bool Buffur_Full = FALSE;//定义成全局变量
char buf[64];//定义成全局变量
int buf_conut =0

void DEBUG_USART_IRQHandler(void)
{
    uint8_t ucTemp;

    if (USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET) {
        buf[buf_conut++] = USART_ReceiveData( USART1 );
        PacketCheck();
    }
}
void BufferFlush(u32 BufferSize){
    for(u32 counter=0; counter
}
void PacketCheck(void)
{
    int para_length = 0;
    //Header Check
    if(buf[0]!=0xff){ BufferFlush(buf_conut); buf_conut=0; return; }
    else if(buf_conut==1) return;
        if(buf[1]!=0xff){ BufferFlush(buf_conut); buf_conut=0; return; }
        else if(buf_conut==2) return;
   
    if(buf_conut>2)
    {   
        para_length = buf[2];
        if(buf_conut - 2> para_length)
        {
            for(int i= 0;i
            {
                get_From_PC = buf[i+3];
            }
        }
        if(buf_conut == para_length +2)
        {
            Buffur_Full = TURE;
            gRxHostBufferFlush(buf_conut);
            buf_conut = 0;
        }
    }

}

   
   
  /*
嵌套向量中断控制器 NVIC 配置
中断控制器 NVIC 配置
*/
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 嵌套向量中断控制器组选择 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 配置 USART 为中断源 */
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
/* 抢断优先级为 1 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/* 子优先级为 1 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* 使能中断 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* 初始化配置 NVIC */
NVIC_Init(&NVIC_InitStructure);
}

  工作模式配置
//USART 初始化配置
void Debug_USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
/* 使能 USART GPIO 时钟 */
RCC_AHB1PeriphClockCmd(DEBUG_USART_RX_GPIO_CLK |
DEBUG_USART_TX_GPIO_CLK,
ENABLE);
/* 使能 USART 时钟 */
RCC_APB2PeriphClockCmd(DEBUG_USART_CLK, ENABLE);
/* GPIO 初始化 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* 配置 Tx 引脚为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_PIN ;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
/* 配置 Rx 引脚为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_PIN;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
/* 连接 PXx 到 USARTx_Tx*/
GPIO_PinAFConfig(DEBUG_USART_RX_GPIO_PORT,
DEBUG_USART_RX_SOURCE,
DEBUG_USART_RX_AF);
/* 连接 PXx 到 USARTx__Rx*/
GPIO_PinAFConfig(DEBUG_USART_TX_GPIO_PORT,
DEBUG_USART_TX_SOURCE,
DEBUG_USART_TX_AF);
/* 配置串 DEBUG_USART 模式 */
/* 波特率设置: DEBUG_USART_BAUDRATE */
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
/* 字长(数据位+校验位): 8 */
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
/* 停止位: 1 个停止位 */
USART_InitStructure.USART_StopBits = USART_StopBits_1;
/* 校验位选择:不使用校验 */
USART_InitStructure.USART_Parity = USART_Parity_No;
/* 硬件流控制:不使用硬件流 */
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
/* USART 模式控制:同时使能接收和发送 */
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* 完成 USART 初始化配置 */
USART_Init(DEBUG_USART, &USART_InitStructure);
/* 嵌套向量中断控制器 NVIC 配置 */
NVIC_Configuration();
/* 使能串口接收中断 */
USART_ITConfig(DEBUG_USART, USART_IT_RXNE, ENABLE
/* 使能串口 */
USART_Cmd(DEBUG_USART, ENABLE);
}
GPIO_PinAFConfig 函数接收三个参数,第一个参数为 GPIO 端口,比如 GPIOA;第二个参数是指定要复用的引脚号,比如 GPIO_PinSource10;第三个参数是选择复用外设,比如 GPIO_AF_USART1。该函数最终操作的是 GPIO 复用功能寄存器 GPIO_AFRH 和GPIO_AFRL,分高低两个。

  字符发送
/***************** 发送一个字符 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
/* 发送一个字节数据到 USART */
USART_SendData(pUSARTx,ch);
/* 等待发送数据寄存器为空 */
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
/***************** 发送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
unsigned int k=0;
do {
Usart_SendByte( pUSARTx, *(str + k) );
k++;
} while (*(str + k)!='');
/* 等待发送完成 */
while (USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET) {
}
}
Usart_SendByte 函数用来在指定 USART 发送一个 ASCLL 码值字符,它有两个形参,第一个为 USART,第二个为待发送的字符。它是通过调用库函数 USART_SendData 来实现的,并且增加了等待发送完成功能。通过使用 USART_GetFlagStatus 函数来获取 USART事件标志来实现发送完成功能等待,它接收两个参数,一个是 USART,一个是事件标志。这里我们循环检测发送数据寄存器为空这个标志,当跳出 while 循环时说明发送数据寄存器为空这个事实。
Usart_SendString 函数用来发送一个字符串,它实际是调用 Usart_SendByte 函数发送每个字符,直到遇到空字符才停止发送。最后使用循环检测发送完成的事件标志来实现保证数据发送完成后才退出函数

  USART 中断服务函数
void DEBUG_USART_IRQHandler(void)
{
uint8_t ucTemp;
if (USART_GetITStatus(DEBUG_USART,USART_IT_RXNE)!=RESET) {
ucTemp = USART_ReceiveData( DEBUG_USART );
USART_SendData(DEBUG_USART,ucTemp);
}
}

  这段代码是存放在 stm32f4xx_it.c 文件中的,该文件用来集中存放外设中断服务函数。当我们使能了中断并且中断发生时就会执行中断服务函数。
使能了 USART 接收中断,当 USART 有接收到数据就会执行DEBUG_USART_IRQHandler 函数。 USART_GetITStatus 函数与 USART_GetFlagStatus 函数类似用来获取标志位状态,但 USART_GetITStatus 函数是专门用来获取中断事件标志的,并返回该标志位状态。使用 if 语句来判断是否是真的产生 USART 数据接收这个中断事件,如果是真的就使用 USART 数据读取函数 USART_ReceiveData 读取数据到指定存储区。然后再调用 USART 数据发送函数 USART_SendData 把数据又发送给源设备。

   
   
   
   
   

   
   
   
   
举报

更多回帖

×
20
完善资料,
赚取积分