久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術學習與研究
當前位置:單片機教程網 >> STM32 >> 瀏覽文章

STM32學習之通用定時器的使用

作者:竹葉聽箏   來源:竹葉聽箏   點擊數:  更新時間:2014年06月19日   【字體:

1STM32F103內部定時器有哪些?

    STM32一共有8個通用16Timer,其中TIMER1TIMER8是高級定時器,其它的TIMER2~TIMER7是普通定時器。
   
此外還有一個Systick(系統滴答定時器),這個定時器通常在操作系統中作為系統的任務切換周期。
   
還有一個RTC,是一個毫秒定時器,支持秒級中斷,用來做實時時鐘計數器。

    看門狗定時器 也可以算一個。

    8個定時器中,Timer1 Timer8是由APB2(輸出最高頻率為72MHZ)預分頻后,再通過一個倍頻器得到時鐘頻率,最高為72MHzTimer2~Timer7則是由APB1(輸出最高頻率為36MHZ)預分頻后,再通過一個倍頻器得到時鐘頻率,最高為36MHz

 

2、如何進行程序編寫     

  這里我通過定時器來控制一個LED0.5s 0.5s ,交替閃爍。當然要讓定時器正常工作起來,還要配置中斷NVIC。定時器計數到某個數,產生中斷,從而進入中斷服務程序,點亮LED燈。

main函數分析:

#include "stm32f10x.h"

 

void GPIO_Config(void)//GPIO配置

{

   GPIO_InitTypeDef GPIO_InitStructure;

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//使能gpioc的時    

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;                 //選擇管腳PC.13LED

   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //管腳速度為50M

 

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          //設置輸出模式為推挽輸出

   GPIO_Init(GPIOC, &GPIO_InitStructure);             //將上述設置寫入到GPIOC里去

}

 

      void NVIC_Config(void)                                           //中斷控制器的配置

{

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);                   //優先組設置

NVIC_InitStructure.NVIC_IRQChannel =TIM2_IRQn ;           //TIM2中斷選通

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;      //搶占優先級

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;           //子優先級

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         //使能中斷控制

NVIC_Init(&NVIC_InitStructure);

}

void Timer_Config(void)         //定時器的配置

{

       TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;   

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);  //Timer2 時鐘使能

TIM_DeInit(TIM2);                              //復位TIM2定時器      

TIM_TimeBaseStructure.TIM_Period=1000;          //定時器周期

TIM_TimeBaseStructure.TIM_Prescaler=36000-1;     //預分頻數

TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;   //TIM2時鐘分頻,1表示不分頻

TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//定時器計數為向上計數模式

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);     

TIM_ClearFlag(TIM2, TIM_FLAG_Update);           //清除定時器2的溢出標志位

TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);      //使能定時器2溢出中斷

TIM_Cmd(TIM2, ENABLE);                       //定時器2使能

}

 

 

int main(void)

{

  SystemInit();//初始化時鐘,配置為72MHz,我試過將這句注釋掉,好像不影響結果。查            

              了一下,在配置

               //main函數之前的啟動代碼有這樣一句  LDR R0, =SystemInit,我疑惑的是難               

             道啟動的時候就配成72Mhz? 

    GPIO_Config();

       NVIC_Config();

       Timer_Config();

  while(1)

       { 

    ;     

  }

}

 

 


中斷服務函數

void TIM2_IRQHandler(void)

{

static int flag_bit=0;//定義一個標志位

      

if ( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET ) //判斷中斷溢出標志為是否為1

       {

   TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update); //清除溢出中斷標志位

               flag_bit = !flag_bit;

               if(flag_bit == 1)

          GPIO_SetBits(GPIOC, GPIO_Pin_13);             //熄滅LED

               if(flag_bit == 0)

     GPIO_ResetBits(GPIOC, GPIO_Pin_13);           //點亮LED

        }

 

   這個函數是寫在stm32f10x_it.c 里面的,我對TIM2_IRQHandler()函數的理解應該是這樣的:

    首先由定時器定時,定時好了產生中斷溢出標志位,發送中斷

    然后進入中斷服務函數TIM2_IRQHandler(),進入函數之后要做的就是清除中斷溢出 

    標志位。

    最后再執行函數里的其他內容。

定時器定時時間計算是這兩句:

                   TIM_TimeBaseStructure.TIM_Period=1000;          //定時器周期

                   TIM_TimeBaseStructure.TIM_Prescaler=36000-1;     //預分頻數

   Prescaler可以理解為定時器的基數是72M  /  Prescaler+1  = 2000k,也就是500us Period 可以理解為要計數多少次,這里是1000次。 所以就是每500us記一次,計數1000次,就是500ms

公式為:

   Period / (72M / (Prescaler+1) )=____

    1000 / (72 M/ (35999+1) )  =  0.5

 

 

我有的一些疑問:1、進入中斷函數之后,定時器要干些什么,是不是就停止計數了?

                2、計數記到1000發生中斷,計數值是不是有自動清零

  問題先放到這兒,邊學習,邊解決。             

               

 

 

3仿真結果觀察

前面第三章已經過如何仿真波形的步驟,可以參看前面。點擊setup 按鈕 會彈出一個窗口,在窗口的右上邊,有個new的按鈕,點擊后輸入 PORTC.13

 

仿真運行結果如下:


可以從仿真結果中觀察到,方波的周期為一秒。占空比為0.5 ,跟預期一致。

 

4對第四章串口的補充

  第四章介紹了串口的打印函數printf 是如何調用實現的。但要使用keil自帶的微庫microLIB ,那能不能不使用這個微庫呢。我參照野火的教程,修改了程序,自己編寫usart_printf()函數來實現打印的功能。

 

   USRT1的配置不改變,主要的就是添加打印函數實現串口輸出功能。代碼感覺可能很長,但無非就是一些判斷,看看字符串最后一位是不是\0 ,不是的話,遇到轉義字符,/n /r 怎么做,以及將數字轉換成字符這些。

這些很多時候我都沒注意:

  1  這一句while ( *Data != 0)     // 判斷是否到達字符串結束符

我們平時不是都用 \0 嗎? 0開始我還沒反應過來。 其實ASCII的十六進制的0 就是\0

 如果要使用\0while ( *Data !='\0') ,主要要加單引號表字符串,上面沒有加就是十六進制,后面的也就能明白了。

  2stdarg.h這個函數,以前都沒見過,但學習就是要學習新知識。 知識改變命運,我一直都相信這句!

  3char *itoa(int value, char *string, int radix)  是指針函數,返回值是一個地址

  4、其他的都是涉及指針的操作,所以C指針一定要學好,沒學好,不要緊,趁這個機會把它弄明白,當我看懂了下面這些,也就明白了。

 

#ifndef __usart_debug_H

#define    __usart_debug_H

 

#include "stm32f10x.h"

#include   //stdarg.hC語言中C標準函數庫的頭文件,目的為讓函數能夠接收可變參數。

 

extern void usart_debug_config(void);  //提供給外部函數調用usart_debug_config()函數。

//

//  函數名:itoa

//  描述  :將整形數據轉換成字符串

// 輸入  -radix =10 表示10進制,其他結果為0

//         -value 要轉換的整形數

 //       -buf 轉換后的字符串

 //       -radix = 10

 * 輸出  :無

 * 返回  :無

 * 調用  :被USART1_printf()調用

 *

static char *itoa(int value, char *string, int radix)

{

    int     i, d;

    int     flag = 0;

    char    *ptr = string;

 

    //This implementation only works for decimal numbers.  

    if (radix != 10)

    {

        *ptr = 0;

        return string;

    }

 

   if (!value)

    {

        *ptr++ = 0x30;

        *ptr = 0;

        return string;

    }

 

    //if this is a negative value insert the minus sign.

    if (value < 0)

    {

        *ptr++ = '-';

 

        // Make the value positive.

        value *= -1;

    }

 

    for (i = 10000; i > 0; i /= 10)

    {

        d = value / i;

 

        if (d || flag)

        {

            *ptr++ = (char)(d + 0x30);

            value -= (d * i);

            flag = 1;

        }

    }

 

    // Null terminate the string. 

    *ptr = 0;

 

    return string;

 

} //NCL_Itoa

 

 

 // 函數名:USART1_printf

 //描述  :格式化輸出,類似于C庫中的printf,但這里沒有用到C

 //輸入  -USARTx 串口通道,這里只用到了串口1,即USART1

 //                -Data   要發送到串口的內容的指針

//                     -...    其他參數

// 輸出  :無

 // 返回  :無

 //調用  :外部調用

//         典型應用USART1_printf( USART1, "\r\n this is a demo \r\n" );

//                        USART1_printf( USART1, "\r\n %d \r\n", i );

//                        USART1_printf( USART1, "\r\n %s \r\n", j );

//

static   void USART1_printf(USART_TypeDef* USARTx, uint8_t *Data,...)

{

       const char *s;

  int d;  

  char buf[16];

 

  va_list ap;        // va_list ap  va_start(ap, Data)以及后面的va_arg() 都來自 stdarg.h

  va_start(ap, Data);//具體用法請參照相關資料。

 

       while ( *Data != 0)     // 判斷是否到達字符串結束符

       {                                                   

              if ( *Data == 0x5c )  // '\'  ASCII 0x5c就是轉義字符'\'

              {                                                              

                     switch ( *++Data )

                     {

                            case 'r':                                                        //回車符

                                   USART_ClearFlag(USART2,USART_FLAG_TC);

                                   USART_SendData(USARTx, 0x0d);

                              while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET );

                                   Data ++;

                                   break;

 

                            case 'n':                                                        //換行符

                                   USART_ClearFlag(USART2,USART_FLAG_TC);

                                   USART_SendData(USARTx, 0x0a);    

                            while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET );

                                   Data ++;

                                   break;

                           

                            default:

                                   Data ++;

                                break;

                     }                  

              }

              else if ( *Data == '%')

              {                                                               //

                     switch ( *++Data )

                     {                         

                            case 's':                                                                     //字符串

                                   s = va_arg(ap, const char *);

          for ( ; *s; s++)

                                   {

                                          USART_ClearFlag(USART2,USART_FLAG_TC);

                                          USART_SendData(USARTx,*s);

                                          while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET );

          }

                                   Data++;

          break;

 

        case 'd':                                                                   //十進制

          d = va_arg(ap, int);

          itoa(d, buf, 10);

          for (s = buf; *s; s++)

                                   {

                                     USART_ClearFlag(USART2,USART_FLAG_TC);

                                          USART_SendData(USARTx,*s);

                                          while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET );

          }

                                   Data++;

          break;

                             default:

                                          Data++;

                                break;

                     }           

              } //end of else if 

              else  {

                          USART_ClearFlag(USART2,USART_FLAG_TC);

                          USART_SendData(USARTx, *Data++);

                          while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET );

                    }      

                     while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET );

       }

}

 

#endif // __USART1_H 

 

軟件仿真中的效果圖:

 波形圖 IO口狀態 串口輸出 都在下面圖里了

 



5工程代碼   

  定時器中斷                    百度云盤:http://pan.baidu.com/s/1mzOIE

  定時器中斷帶串口          百度云盤:http://pan.baidu.com/s/1dD06Olb

  野火串口工程                 百度云盤:http://pan.baidu.com/s/1o6pzjZ0

  word文檔教程                 百度文庫: 

關閉窗口

相關文章

主站蜘蛛池模板: 国产视频一区二区三区四区五区 | 岛国精品 | 亚洲成人精品免费 | 亚洲性爰 | 亚洲综合色视频在线观看 | 羞羞视频免费在线观看 | 精品国产18久久久久久二百 | 国产精品久久久久久一级毛片 | 草草草网站 | 性高朝久久久久久久3小时 av一区二区三区四区 | 毛片免费看的 | 久久精品在线 | 亚洲国产情侣 | 中国免费黄色片 | 精品久久久久久久 | 99色综合| 久久精品视频亚洲 | 99爱免费 | 波多野吉衣在线播放 | 久久久久久国产精品免费免费 | 天天爽天天干 | 99精品九九| 欧美日韩手机在线观看 | 国产精品国产三级国产aⅴ中文 | 黑人一级黄色大片 | 看亚洲a级一级毛片 | 国产精品亚洲一区二区三区在线观看 | 日韩在线免费 | 一区二区免费在线视频 | 99精品欧美一区二区三区 | 欧美一区二区三区电影 | www.日韩av.com | 日本久久网| 免费成人午夜 | 超碰在线人人干 | 亚洲精品一二三区 | 手机在线观看 | 日韩淫片免费看 | 男人av在线播放 | 99精品一区| 国产精品亚洲精品 |