博客首页 | 排行榜 |

wolaiye945的博客

我的STM32F学习之路

个人档案
博文分类
【原创】STM32中用USART实现RTC计数设置  2009-02-07 16:35
权衡了一下还是决定用串口来设定RTC的时间,这样使用调试比较方便,也顺便复习一下USART。由于涉及的方面比较多,缺少任何一步都可能导致失败,一定要认真自习的修改和调试。这次虽然比较顺利,但还是调试了将近3个小时才达到我想要的效果。把心得和函数跟大家分享一下,希望大家早日成功~!

首先是STM32的USART配置,如果对原理比较了解,简单看一下LM就可以上手了,使用比较方便。
初始化流程及函数如下:(参考了例程,注释比较详细了,有问题再留言讨论吧)

1、配置IO口
2、设置UART时钟,各项参数,并使能中断
3、写发送函数(查询方式)
4、写接收函数(中断方式)
5、写应用函数(也就是分析接受到的数据并给RTC计数器置数)

另外中断函数需要在NVIC中使能通道,并说明优先级。


/*******************************************************************************
* Function Name   : UART1_GPIO_Configuration
* Description        : Configures the uart1 GPIO ports.
* Input                    : None
* Output                 : None
* Return                 : None
*******************************************************************************/
void UART1_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// Configure USART1_Tx as alternate function push-pull
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

// Configure USART1_Rx as input floating
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);  
}

然后是配置串口参数


/* 如果使用查询的方式发送和接收数据 则不需要使能串口的中断(默认)
   如果需要使用中断的方式发送和接收数据 则需要使能串口中断
    函数原形 void USART_ITConfig(USART_TypeDef* USARTx, u16 USART_IT, FunctionalState NewState)
    功能描述 使能或者失能指定的 USART 中断
   
       USART_IT                   描述
       USART_IT_PE       奇偶错误中断
       USART_IT_TXE    发送中断
       USART_IT_TC       传输完成中断
       USART_IT_RXNE 接收中断
       USART_IT_IDLE    空闲总线中断
       USART_IT_LBD    LIN中断检测中断
       USART_IT_CTS    CTS中断
       USART_IT_ERR    错误中断

*/


/*******************************************************************************
* Function Name   : UART1_Configuration
* Description        : Configures the uart1
* Input                    : None
* Output                 : None
* Return                 : None
*******************************************************************************/
void UART1_Configuration(void)
{
   USART_DeInit(USART1); //缺省设置
      //设置时钟
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
   // Configure USART1_Tx as alternate function push-pull
   // and Configure USART1_Rx as input floating
   UART1_GPIO_Config();

   USART_InitTypeDef USART_InitStructure;
   /* USART1 configured as follow:
       - BaudRate = 9600 baud  
       - Word Length = 8 Bits
       - One Stop Bit
       - No parity
       - Hardware flow control disabled (RTS and CTS signals)
       - Receive and transmit enabled
   这就是默认参数,虽然可以用USART_StructInit(&USART_InitStructure);实现,但还是这样踏实。
   */
   USART_InitStructure.USART_BaudRate = 9600;
   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;
  
   /* Configure the USART1*/
   USART_Init(USART1, &USART_InitStructure);

   /* Enable USART1 Receive and Transmit interrupts */
   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);


   /* Enable the USART1 */
   USART_Cmd(USART1, ENABLE);  
}



/*******************************************************************************
* Function Name   : Uart1_PutChar
* Description        : 送一个字符到USART1
* Input                : None
* Output              : None
* Return               : None
*******************************************************************************/
u8 Uart1_PutChar(u8 ch)
{
/* Write a character to the USART1 */
USART_SendData(USART1, (u8) ch);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
{
}
return ch;
}



/*******************************************************************************
* Function Name   : Uart1_PutString
* Description        : print a string to the uart1
* Input                : buf为发送数据的头指针 , len为发送字符的长度
* Output              : None
* Return               : None
*******************************************************************************/
void Uart1_PutString(u8* buf , u8 len)
{
for(u8 i=0;i {
       Uart1_PutChar(*buf++);
}
}


如果UART使用中断发送数据,则需要修改stm32f10x_it.c中的串口中断函数,并且需要修改NVIC_Configuration(void)函数申请通道

在中断里面的处理流程是根据收发双方的协议或指令规范来设置的。
这里简化一下,如果接收到5个字符或者接收到0x0D则认为一条指令接收完毕,关闭中断,并把全局标志位UartHaveData置1

/*******************************************************************************
* Function Name   : USART1_IRQHandler
* Description        : This function handles USART1 global interrupt request.
* Input                : None
* Output              : None
* Return               : None
*******************************************************************************/
void USART1_IRQHandler(void)
{
  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
   {
    /* Read one byte from the receive data register */
    RxBuffer[ RxCounter ] = USART_ReceiveData(USART1);  
    RxCounter++;
    if( RxCounter == 10 || 0x0D == RxBuffer[ RxCounter-1 ] )//接受完毕条件,超过20个字符或回车
    {
     /* Disable the USART1 Receive interrupt */
     USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
     RxBuffer[ RxCounter ] = '\0';
     UartHaveData = 1;
     RxCounter = 0;
    }
  }
}


//修改hw_config里面的NVIC_Configuration函数

/*******************************************************************************
* Function Name   : NVIC_Configuration
* Description        : Configures NVIC and Vector Table base location.
* Input                : None
* Output              : None
* Return               : None
*******************************************************************************/
void NVIC_Configuration(void)
{
   NVIC_InitTypeDef NVIC_InitStructure;
  
#ifdef   VECT_TAB_RAM
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else   /* VECT_TAB_FLASH   */
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
  
   /* Configure the NVIC Preemption Priority Bits */  
   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
   /* Enable the USART1 Interrupt */
   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
  
//其他中断的通道申请省略~
}
还有几个关于数据缓冲和结束标志的全局变量需要在头文件中声明一下,在此就不赘述了。

最后要是现实时钟的设置,很简单,就是应用函数的设计了。
在主函数中或者定时中断函数中加入如下代码即可:
if (UartHaveData)
     {
       setpos=0;
        while (RxBuffer[setpos]!='t') setpos++;
        SetTime=(RxBuffer[setpos+1]-'0')*10+(RxBuffer[setpos+2]-'0');
        SetTime*=3600;
        SetTime+=((RxBuffer[setpos+3]-'0')*10+(RxBuffer[setpos+4]-'0'))*60;
        RTC_SetCounter(SetTime);
        Uart1_PutString(RxBuffer,10);//返回数据,检验是否正常
        UartHaveData=0;
        USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
     }
/*************************************************
*时间更新指令格式为发送字符串"thhmm"即可修正时间到hh:mm:00;
*例如用"t1530"就可以更新时间到15:30:00;
*上述代码流程:当接受结束标志为1时,即认为指令接受结束,同时搜索
当前缓冲区数组,找到't'的位置,然后将后面的数字转换成需要的参数即可
*************************************************/

最后还要说明一个问题,上篇文章中的一个变量的定义出了问题,就是计数存储变量RTCCounterValue的问题,当时我定义为u16,这样最大计数值65536小于24小时对应的秒数,会导致24小时制提前溢出。所以修正方法要么采用12小时制,要么如此定义 u32 RTCCounterValue = RTC_GetCounter(); 即可。
类别:心得体会 |
上一篇:【转帖】关于STM32定时器16位拓展32位的探讨 | 下一篇:【原创】STM32实时时钟RTC探究2
以下网友评论只代表其个人观点,不代表本网站的观点或立场