日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 單片機(jī) > 單片機(jī)
[導(dǎo)讀] 勉勉強(qiáng)強(qiáng)看懂一行程序   繼續(xù)學(xué)習(xí)中,先把開發(fā)板自帶一個(gè)例子做了些精簡,以免看得嚇人。。。。      就是這個(gè),讓PORTD上接的4個(gè)LED分別點(diǎn)亮。   開始研究代碼   int main(void)   {   

 勉勉強(qiáng)強(qiáng)看懂一行程序

  繼續(xù)學(xué)習(xí)中,先把開發(fā)板自帶一個(gè)例子做了些精簡,以免看得嚇人。。。。
  
  就是這個(gè),讓PORTD上接的4個(gè)LED分別點(diǎn)亮。
  開始研究代碼
  int main(void)
  {
  Init_All_Periph();
  。。.。。.
  看到這一行,開始跟蹤,于是又看到了下面的內(nèi)容
  void Init_All_Periph(void)
  {
  RCC_Configuration();
  。。.。。.
  繼續(xù)跟蹤
  void RCC_Configuration(void)
  {
  SystemInit();
  。。.。。.
  這行代碼在system_stm32f10x.c中找到了。
  void SystemInit (void)
  {
  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  /* Set HSION bit */
  RCC-》CR |= (uint32_t)0x00000001;
  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
  #ifndef STM32F10X_CL
  RCC-》CFGR &= (uint32_t)0xF8FF0000;
  #else
  RCC-》CFGR &= (uint32_t)0xF0FF0000;
  #endif /* STM32F10X_CL */
  /* Reset HSEON, CSSON and PLLON bits */
  RCC-》CR &= (uint32_t)0xFEF6FFFF;
  /* Reset HSEBYP bit */
  RCC-》CR &= (uint32_t)0xFFFBFFFF;
  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  RCC-》CFGR &= (uint32_t)0xFF80FFFF;
  #ifndef STM32F10X_CL
  /* Disable all interrupts and clear pending bits */
  RCC-》CIR = 0x009F0000;
  #else
  /* Reset PLL2ON and PLL3ON bits */
  RCC-》CR &= (uint32_t)0xEBFFFFFF;
  /* Disable all interrupts and clear pending bits */
  RCC-》CIR = 0x00FF0000;
  /* Reset CFGR2 register */
  RCC-》CFGR2 = 0x00000000;
  #endif /* STM32F10X_CL */
  /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
  /* Configure the Flash Latency cycles and enable prefetch buffer */
  SetSysClock();
  }
  這一長串的又是什么,如何來用呢?看來,偷懶是不成的了,只能回過頭去研究STM32的時(shí)鐘構(gòu)成了。
  相當(dāng)?shù)膹?fù)雜。

 系統(tǒng)的時(shí)鐘可以有3個(gè)來源:內(nèi)部時(shí)鐘HSI,外部時(shí)鐘HSE,或者PLL(鎖相環(huán)模塊)的輸出。它們由RCC_CFGR寄存器中的SW來選擇。
  SW(1:0):系統(tǒng)時(shí)鐘切換
  由軟件置’1’或清’0’來選擇系統(tǒng)時(shí)鐘源。 在從停止或待機(jī)模式中返回時(shí)或直接或間接作為系統(tǒng)時(shí)鐘的HSE出現(xiàn)故障時(shí),由硬件強(qiáng)制選擇HSI作為系統(tǒng)時(shí)鐘(如果時(shí)鐘安全系統(tǒng)已經(jīng)啟動(dòng))
  00:HSI作為系統(tǒng)時(shí)鐘;
  01:HSE作為系統(tǒng)時(shí)鐘;
  10:PLL輸出作為系統(tǒng)時(shí)鐘;
  11:不可用。
  ////////////////////////////////////////////////////////////////////
  PLL的輸出直接送到USB模塊,經(jīng)過適當(dāng)?shù)姆诸l后得到48M的頻率供USB模塊使用。
  系統(tǒng)時(shí)鐘的一路被直接送到I2S模塊;另一路經(jīng)過AHB分頻后送出,送往各個(gè)系統(tǒng),其中直接送往SDI,F(xiàn)MSC,AHB總線;8分頻后作為系統(tǒng)定時(shí)器時(shí)鐘;經(jīng)過APB1分頻分別控制PLK1、定時(shí)器TIM2~TIM7;經(jīng)過APB2分頻分別控制PLK2、定時(shí)器TIM1~TIM8、再經(jīng)分頻控制ADC;
  由此可知,STM32F10x芯片的時(shí)鐘比之于51、AVR、PIC等8位機(jī)要復(fù)雜復(fù)多,因此,我們立足于對(duì)著芯片手冊(cè)來解讀程序,力求知道這些程序代碼如何使用,為何這么樣使用,如果自己要改,可以修改哪些部分,以便自己使用時(shí)可以得心應(yīng)手。
  單步執(zhí)行,看一看哪些代碼被執(zhí)行了。
  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  /* Set HSION bit */
  RCC-》CR |= (uint32_t)0x00000001;
  
  這是RCC_CR寄存器,由圖可見,HSION是其bit 0位。
  HSION:內(nèi)部高速時(shí)鐘使能
  由軟件置’1’或清零。
  當(dāng)從待機(jī)和停止模式返回或用作系統(tǒng)時(shí)鐘的外部4-25MHz時(shí)鐘發(fā)生故障時(shí),該位由硬件置’1’來啟動(dòng)內(nèi)部8MHz的RC振蕩器。當(dāng)內(nèi)部8MHz時(shí)鐘被直接或間接地用作或被選擇將要作為系統(tǒng)時(shí)鐘時(shí),該位不能被清零。
  0:內(nèi)部8MHz時(shí)鐘關(guān)閉;
  1:內(nèi)部8MHz時(shí)鐘開啟。
  ///////////////////////////////////////////////////////////////////////
  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
  #ifndef STM32F10X_CL
  RCC-》CFGR &= (uint32_t)0xF8FF0000;
  
  這是RCC_CFGR寄存器
  該行程序清零了MC0[2:0]這三位,和ADCPRE[1:0],ppre2[2:0],PPRE1[2:0],HPRE[3:0],SWS[1:0]和SW[1:0]這16位。
  /*
  MCO: 微控制器時(shí)鐘輸出,由軟件置’1’或清零。
  0xx:沒有時(shí)鐘輸出;
  100:系統(tǒng)時(shí)鐘(SYSCLK)輸出;
  101:內(nèi)部8MHz的RC振蕩器時(shí)鐘輸出;
  110:外部4-25MHz振蕩器時(shí)鐘輸出;
  111:PLL時(shí)鐘2分頻后輸出。
  */
  /* Reset HSEON, CSSON and PLLON bits */
  RCC-》CR &= (uint32_t)0xFEF6FFFF;
  清零了PLLON,HSEBYP,HSERDY這3位。
  /* Reset HSEBYP bit */
  RCC-》CR &= (uint32_t)0xFFFBFFFF;
  清零了HSEBYP位 ///???為什么不一次寫??
  HSEBYP:外部高速時(shí)鐘旁路,在調(diào)試模式下由軟件置’1’或清零來旁路外部晶體振蕩器。只有在外部4-25MHz振蕩器關(guān)閉的情況下,才能寫入該位。
  0:外部4-25MHz振蕩器沒有旁路;
  1:外部4-25MHz外部晶體振蕩器被旁路。
  所以要先清HSEON位,再清該位。
  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  RCC-》CFGR &= (uint32_t)0xFF80FFFF;
  清零了:USBPRE,PLLMUL,PLLXTPR,PLLSRC共7位
  /* Disable all interrupts and clear pending bits */
  RCC-》CIR = 0x009F0000;
  ////這個(gè)暫不解讀
  SetSysClock();
 跟蹤進(jìn)入該函數(shù),可見一連串的條件編譯:

 
  單步運(yùn)行,執(zhí)行的是:
  #elif defined SYSCLK_FREQ_72MHz
  SetSysClockTo72();
  為何執(zhí)行該行呢,找到SYSCLK_PREQ_**的相關(guān)定義,如下圖所示。
  
  這樣就得到了我們所要的一個(gè)結(jié)論:如果要更改系統(tǒng)工作頻率,只需要在這里更改就可以了。
  可以繼續(xù)跟蹤進(jìn)入這個(gè)函數(shù)來觀察如何將工作頻率設(shè)定為72MHz的。
  static void SetSysClockTo72(void)
  {
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
  /* Enable HSE */
  RCC-》CR |= ((uint32_t)RCC_CR_HSEON);
  //開啟HSE
  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
  HSEStatus = RCC-》CR & RCC_CR_HSERDY;
  StartUpCounter++;
  } while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));
  //等待HSE確實(shí)可用,這有個(gè)標(biāo)志,即RCC_CR寄存器中的HSERDY位(bit 17),這個(gè)等待不會(huì)無限長,有個(gè)超時(shí)策略,即每循環(huán)一次計(jì)數(shù)器加1,如果計(jì)數(shù)的次數(shù)超過HSEStartUp_TimeOut,就退出循環(huán),而這個(gè)HSEStartUp_TimeOut在stm32f10x.h中定義,
  #define HSEStartUp_TimeOut ((uint16_t)0x0500) /*!《 Time out for HSE start up */
  ///////////////////////////////////////////////////////////////////////////////////////////////
  if ((RCC-》CR & RCC_CR_HSERDY) != RESET)
  {
  HSEStatus = (uint32_t)0x01;
  }
  else
  {
  HSEStatus = (uint32_t)0x00;
  }
  ///再次判斷HSERDY標(biāo)志位,并據(jù)此給HSEStatus變量賦值。
  if (HSEStatus == (uint32_t)0x01)
  {
  /* Enable Prefetch Buffer */
  FLASH-》ACR |= FLASH_ACR_PRFTBE;
  /* Flash 2 wait state */
  FLASH-》ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
  FLASH-》ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
  /* HCLK = SYSCLK */
  RCC-》CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
  //找到定義: #define RCC_CFGR_HPRE_DIV1 ((uint32_t)0x00000000) /*!《 SYSCLK not divided */
  /* PCLK2 = HCLK */
  RCC-》CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
  //找到定義:#define RCC_CFGR_PPRE2_DIV1 ((uint32_t)0x00000000) /*!《 HCLK not divided */
  /* PCLK1 = HCLK */
  RCC-》CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
  //找到定義:#define RCC_CFGR_PPRE1_DIV2 ((uint32_t)0x00000400) /*!《 HCLK divided by 2 */
  #ifdef STM32F10X_CL
  ……
  #else
  /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
  RCC-》CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
  RCC_CFGR_PLLMULL));
  RCC-》CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
  #endif /* STM32F10X_CL */
  //以上是設(shè)定PLL的倍頻系數(shù)為9,也就是說,這個(gè)72M是在外部晶振為8M時(shí)得到的。
  /* Enable PLL */
  RCC-》CR |= RCC_CR_PLLON;
  /* Wait till PLL is ready */
  while((RCC-》CR & RCC_CR_PLLRDY) == 0)
  {
  }
  /* Select PLL as system clock source */
  RCC-》CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
  RCC-》CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
  /* Wait till PLL is used as system clock source */
  while ((RCC-》CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
  {
  }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock
  configuration. User can add here some code to deal with this error */
  /* Go to infinite loop */
  while (1)
  {
  }
  }
  }

  至此,我們可以歸納幾條:
  (1) 時(shí)鐘源有3個(gè)
 ?。?) 開機(jī)時(shí)默認(rèn)是HSI起作用,可以配置為所要求的任意一個(gè)時(shí)鐘
 ?。?) 配置時(shí)必須按一定的順序來打開或都關(guān)閉一些位,并且各時(shí)鐘起作用有一定的時(shí)間,因此要利用芯片內(nèi)部的標(biāo)志位來判斷是否可以執(zhí)行下一步。
  (4) 如果外部時(shí)鐘、PLL輸出失效,系統(tǒng)可以自動(dòng)回復(fù)到HSI(開啟時(shí)鐘安全系統(tǒng))
 ?。?) HSI的頻率準(zhǔn)確度可以達(dá)到+/- 1%,如果有必要時(shí),還可以用程序來調(diào)整這個(gè)頻率,可調(diào)的范圍大致在200KHz左右。
  最后讓我們來感受一下勞動(dòng)的果實(shí)吧--試著改改頻率看有何反應(yīng)。
  為查看更改后的效果,先記錄更改前的數(shù)據(jù)。將調(diào)試切換到仿真,在第一條:
  Delay(0xAFFFF);
  指令執(zhí)行前后,分別記錄下Status和Sec
  Status:2507 3606995
  Sec:0.00022749 0.05028982
  將振蕩頻率更改為36MHz,即
  。。.
  #define SYSCLK_FREQ_36MHz 36000000 //去掉該行的注釋
  /* #define SYSCLK_FREQ_48MHz 48000000 */
  /* #define SYSCLK_FREQ_56MHz 56000000 */
  /*#define SYSCLK_FREQ_72MHz 72000000*/ //將該行加上注釋
  再次運(yùn)行,結(jié)果如下:
  Status:2506 3606994
  Sec:0.00008478 0.10036276
  基本上是延時(shí)時(shí)間長了一倍。改成硬件仿真,將代碼寫入板子,可以看到LED閃爍的頻率明顯變慢了。

IO研究

  前面的例子研究了時(shí)鐘,接下來就來了解一下引腳的情況
  Main.c中,有關(guān)I/O口的配置代碼如下:
  void GPIO_Configuration(void)
  {
  GPIO_InitTypeDef GPIO_InitStructure;
  /* Configure IO connected to LD1, LD2, LD3 and LD4 leds *********************/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
  這幾行代碼是將GPIOD的第8,9,10和11引腳配置成輸出,并且還可以設(shè)定輸出引腳的速度(驅(qū)動(dòng)能力?),這里設(shè)定為 50MHz,這應(yīng)該是常用的,還有可以設(shè)置為2MHz的。那么如何將引腳設(shè)置成輸入呢?查看電路原理圖,GPIOD.0~GPIO.4是接一個(gè)搖桿的5個(gè)按鈕的,因此,下面嘗試著將它們?cè)O(shè)置成為輸入端。
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
  第1行和第3行完全是照抄,第2行那個(gè)GPIO_Mode_IN_FLOATING是在stm32f10x_gpio.h中找到的。
  
  當(dāng)然是因?yàn)檫@里還有GPIO_Mode_Out_PP,所以猜測(cè)應(yīng)該是它了。至于還有其他那么多的符號(hào)就不管了。
  定義完成,編譯完全通過,那就接下來準(zhǔn)備完成下面的代碼了。
  int main(void)
  {
  Init_All_Periph();
  while(1)
  { if( GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_0)) //1
  { GPIO_ResetBits(GPIOD, GPIO_Pin_8);
  }
  else
  { /* Turn on LD1 */
  GPIO_SetBits(GPIOD, GPIO_Pin_8);
  /* Insert delay */
  }
  。。.。。.
  標(biāo)號(hào)為1的行顯然其作用是判斷GPIOD.0引腳是0還是1。這個(gè)函數(shù)是在stm32f10x_gpio.c中找到的。
  uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
  {
  uint8_t bitstatus = 0x00;
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
  if ((GPIOx-》IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
  {
  bitstatus = (uint8_t)Bit_SET;
  }
  else
  {
  bitstatus = (uint8_t)Bit_RESET;
  }
  return bitstatus;
  }
  雖然程序還有很多符號(hào)看不懂(沒有去查),但憑感覺它應(yīng)該是對(duì)某一個(gè)引腳的狀態(tài)進(jìn)行判斷,因?yàn)檫@個(gè)函數(shù)的類型是uint8_t,估計(jì)stm32沒有bit型函數(shù)(需要驗(yàn)證),所以就用了uint8_t型了),如果是讀的端口的值,應(yīng)該用uint16_t型。這一點(diǎn)在下面也可以得到部分的驗(yàn)證:
  uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx)
  uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)
  這些函數(shù)是讀引腳及輸出寄存器的數(shù)據(jù)的。

 再次編譯,也是順利通過,依法炮制,將其他三個(gè)引腳輸入控制LED的代碼也寫上,為保險(xiǎn)起見,先用軟件仿真,免得反復(fù)擦寫FLASH(順便說一句,目前還沒有搞定將代碼寫入RAM及從RAM中執(zhí)行)
  
  進(jìn)入仿真后打開外圍部件接口,單步執(zhí)行,果然如同設(shè)想那樣運(yùn)作了,單擊Pins 0后面的勾,再次運(yùn)行,果然PIN8后面的勾沒了。做到這里,就感覺到用keil的好處了,這塊熟啊,幾乎沒有花時(shí)間在上面,一用就成了。
  至此,按我的習(xí)慣,要翻開STM32F的數(shù)據(jù)手冊(cè),研究一下其IO端口了。下面是數(shù)據(jù)手冊(cè)中的一段話:
  -------------------------------------
  每個(gè)GPI/O端口有兩個(gè)32位配置寄存器(GPIOx_CRL,GPIOx_CRH),兩個(gè)32位數(shù)據(jù)寄存器(GPIOx_IDR,GPIOx_ODR),一個(gè)32位置位/復(fù)位寄存器(GPIOx_BSRR),一個(gè)16位復(fù)位寄存器(GPIOx_BRR)和一個(gè)32位鎖定寄存器(GPIOx_LCKR)。
  根據(jù)數(shù)據(jù)手冊(cè)中列出的每個(gè)I/O端口的特定硬件特征, GPIO端口的每個(gè)位可以由軟件分別配置成多種模式。
  ─ 輸入浮空
  ─ 輸入上拉
  ─ 輸入下拉
  ─ 模擬輸入
  ─ 開漏輸出
  ─ 推挽式輸出
  ─ 推挽式復(fù)用功能
  ─ 開漏復(fù)用功能
  ----------------------------------------------------
  當(dāng)然,數(shù)據(jù)手冊(cè)上關(guān)于IO端口的描述是很多很多的,我也只是大概地了解了一下,真正要設(shè)計(jì)產(chǎn)品時(shí),肯定還要細(xì)看。但至少,知道了IO端口復(fù)位后處于浮空狀態(tài),也就是其電平狀態(tài)由外圍電路決定,這很重要,如果設(shè)計(jì)工業(yè)品的話,這是必須要確定的;知道了IO引腳可以兼容5V電源;知道了在什么地方可以找到這些引腳在庫中的定義而不必看著數(shù)據(jù)手冊(cè)去控制那些位;也知道了這些引腳的一些基本操作函數(shù)(連猜帶蒙帶測(cè)試應(yīng)該可以搞定大部分功能),那么我心里基本就有底啦。
  最后用一段電子熒火蟲(也就是呼吸燈)的簡單程序作為結(jié)束。
  int main(void)
  { uint8_t Count;
  uint32_t DelayTim=“0x1000”; //基數(shù)
  uint32_t ChangTim=“0x2000”; //每次變化的量
  Init_All_Periph();
  while(1)
  {
  for(Count=0;Count《16;Count++) //漸亮
  {
  GPIO_SetBits(GPIOD, GPIO_Pin_8); //點(diǎn)亮燈
  Delay(DelayTim+Count*ChangTim);
  GPIO_ResetBits(GPIOD, GPIO_Pin_8); //熄滅燈
  Delay(DelayTim+(16-Count)*ChangTim);
  }
  for(Count=16;Count》0;Count--) //漸暗
  {
  GPIO_SetBits(GPIOD, GPIO_Pin_8); //點(diǎn)亮燈
  Delay(DelayTim+Count*ChangTim);
  GPIO_ResetBits(GPIOD, GPIO_Pin_8); //熄滅燈
  Delay(DelayTim+(16-Count)*ChangTim);
  }
  }
  }
  定時(shí)器初步
  接下來研究定時(shí)器。為什么開始研究定時(shí)器了呢?那個(gè)I/O還是剛剛開了頭啊,還有很多很多知識(shí)沒有掌握!不怕,方法論告訴我們:對(duì)事物的認(rèn)識(shí)是螺旋式上升的,所以不要一桿子打到底,想著把I/O口的所有情況都掌握了再學(xué)下面的,那會(huì)是很困難的
  STM32的定時(shí)器是什么樣子的,心里一點(diǎn)底也沒有,還是找個(gè)現(xiàn)成的例子來吧。在ST提供的庫里,有很多的例子
  第一個(gè)就是它了。
  
  把整個(gè)文件夾復(fù)制一份到自己的實(shí)驗(yàn)文件夾中
  
  在Source文件夾中再建立名為APP的文件夾,將上圖中所有源程序文件全部復(fù)制到APP文件夾中。然后將庫所提供的CMSIS文件夾和 STM32F10x_StdPeriph_Driver文件夾復(fù)制到Source文件夾中。然后按照前面的方法建立項(xiàng)目。
  
  這是建好的項(xiàng)目的結(jié)構(gòu)。
  下面開始研究,首先看附帶的readme.txt文件,了解到該例子的大體用途是驗(yàn)證Tim2的Output Compare Timing mode的。于是打開PDF文件,直接翻到下面的位置:
  -----------------------------------------------------------------------------------------

 13.3.8 輸出比較模式
  此項(xiàng)功能是用來控制一個(gè)輸出波形或者指示何時(shí)一段給定的的時(shí)間已經(jīng)到時(shí)。
  當(dāng)計(jì)數(shù)器與捕獲/比較寄存器的內(nèi)容相同時(shí),輸出比較功能做如下操作:
  ● 將輸出比較模式(TIMx_CCMRx寄存器中的OCxM位)和輸出極性(TIMx_CCER寄存器中的CCxP位)定義的值輸出到對(duì)應(yīng)的管腳上。在比較匹配時(shí),輸出管腳可以保持它的電平
 ?。∣CxM=000)、被設(shè)置成有效電平(OCxM=001)、被設(shè)置成無有效電平(OCxM=010)或進(jìn)行翻轉(zhuǎn)(OCxM=011)。
  ● 設(shè)置中斷狀態(tài)寄存器中的標(biāo)志位(TIMx_SR寄存器中的CCxIF位)。
  ● 若設(shè)置了相應(yīng)的中斷屏蔽(TIMx_DIER寄存器中的CCXIE位),則產(chǎn)生一個(gè)中斷。
  ● 若設(shè)置了相應(yīng)的使能位(TIMx_DIER寄存器中的CCxDE位,TIMx_CR2寄存器中的CCDS位選擇DMA請(qǐng)求功能),則產(chǎn)生一個(gè)DMA請(qǐng)求。
  TIMx_CCMRx中的OCxPE位選擇TIMx_CCRx寄存器是否需要使用預(yù)裝載寄存器。
  在輸出比較模式下,更新事件UEV對(duì)OCxREF和OCx輸出沒有影響。
  同步的精度可以達(dá)到計(jì)數(shù)器的一個(gè)計(jì)數(shù)周期。輸出比較模式(在單脈沖模式下)也能用來輸出一個(gè)單脈沖。
  輸出比較模式的配置步驟:
  1. 選擇計(jì)數(shù)器時(shí)鐘(內(nèi)部,外部,預(yù)分頻器)
  2. 將相應(yīng)的數(shù)據(jù)寫入TIMx_ARR和TIMx_CCRx寄存器中
  3. 如果要產(chǎn)生一個(gè)中斷請(qǐng)求和/或一個(gè)DMA請(qǐng)求,設(shè)置CCxIE位和/或CCxDE位。
  4. 選擇輸出模式,例如:必須設(shè)置OCxM=’011’、OCxPE=’0’、CCxP=’0’和CCxE=’1’,當(dāng)計(jì)數(shù)器CNT與CCRx匹配時(shí)翻轉(zhuǎn)OCx的輸出管腳,CCRx預(yù)裝載未用,開啟OCx輸出且高電平有效。
  5. 設(shè)置TIMx_CR1寄存器的CEN位啟動(dòng)計(jì)數(shù)器--------------------------------------------------------------------------------
  說得并不復(fù)雜,但是要弄清楚也絕非易事,況且main.c中一系列的符號(hào)究竟是什么意思也不是那么容易搞清楚的。這些東西搞不清,將來自己編程時(shí),就算想要依葫蘆畫瓢都難。怎么辦呢?可能并沒有多少偷巧的辦法,只能是一步一步地摸索吧。
  進(jìn)入調(diào)試,打開Peripherals-》Timers-》Tim2,出現(xiàn)下面的窗口。
  
  然后單步執(zhí)行程序,并觀察界面的變化,并將這些符號(hào)作為線索,在PDF文件,stmf10x_tim.c等文件中搜索,了解相關(guān)符號(hào)的含義。
  如下圖是執(zhí)行到:while(1)前,也就是所有設(shè)置完成后的圖。
  

沿著這些線索一路追蹤,邊看源程序,邊找數(shù)據(jù)手冊(cè),邊找相關(guān)的頭文件,其他源程序,總算大體有了個(gè)明白,下面將main.c中的部分代碼作為注釋,也算是做點(diǎn)記錄。
  /* Includes ------------------------------------------------------------------*/
  #include “stm32f10x.h”
  //這個(gè)頭文件需要根據(jù)所選擇的芯片進(jìn)行更改
  /* Private variables ---------------------------------------------------------*/
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  TIM_OCInitTypeDef TIM_OCInitStructure; //定義兩個(gè)結(jié)構(gòu)型變量
  __IO uint16_t CCR1_Val = 49152;
  __IO uint16_t CCR2_Val = 32768;
  __IO uint16_t CCR3_Val = 16384;
  __IO uint16_t CCR4_Val = 8192; //
  ErrorStatus HSEStartUpStatus;
  /* Private function prototypes -----------------------------------------------*/
  void RCC_Configuration(void);
  void GPIO_Configuration(void);
  void NVIC_Configuration(void);
  int main(void)
  {
  /* System Clocks Configuration */
  RCC_Configuration();
  /* NVIC Configuration */
  NVIC_Configuration();
  /* GPIO Configuration */
  GPIO_Configuration();
  /* ---------------------------------------------------------------
  TIM2 Configuration: Output Compare Timing Mode:
  TIM2CLK = 36 MHz, Prescaler = 4, TIM2 counter clock = 7.2 MHz
  CC1 update rate = TIM2 counter clock / CCR1_Val = 146.48 Hz
  CC2 update rate = TIM2 counter clock / CCR2_Val = 219.7 Hz
  CC3 update rate = TIM2 counter clock / CCR3_Val = 439.4 Hz
  CC4 update rate = TIM2 counter clock / CCR4_Val = 878.9 Hz
  --------------------------------------------------------------- */
  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 65535; //它對(duì)應(yīng)TIM2_ARR
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  /* 它對(duì)應(yīng)TIM2_PSC,相關(guān)代碼如下(stm32f10x_tim.c中):
  TIMx-》PSC = TIM_TimeBaseInitStruct-》TIM_Prescaler;
  但很奇怪,這里令其為0,然后再在下面設(shè)置為4??為何??
  */
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0200;
  //ClockDivision是對(duì)CKD位進(jìn)行設(shè)置的,但是這個(gè)必須要自己給其賦正確的值
  /*在stm32f10_tim.c文件中是這樣操作的
  TIMx-》CR1 |= (uint32_t)TIM_TimeBaseInitStruct-》TIM_ClockDivision |
  TIM_TimeBaseInitStruct-》TIM_CounterMode;
  */
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  /*計(jì)數(shù)模式,st32f10x_tim.h中定義,其他可用的符號(hào)還有:
  TIM_CounterMode_Up,TIM_CounterMode_Down,TIM_CounterMode_CenterAligned1
  TIM_CounterMode_CenterAligned2,TIM_CounterMode_CenterAligned3
  */
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  /* Prescaler configuration */
  TIM_PrescalerConfig(TIM2, 4, TIM_PSCReloadMode_Immediate);
  /*stm32f10x_tim.c中相關(guān)代碼:
  TIMx-》PSC = Prescaler;
  */
  /* Output Compare Timing Mode configuration: Channel1 *///輸出比較模式
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR1_Val; //預(yù)置值
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //對(duì)CCER中CCxP的操作
  TIM_OC1Init(TIM2, &TIM_OCInitStructure);
  /*對(duì)捕獲/比較使能寄存器(TIMx_CCER)進(jìn)行操作,置CC1E為1 */
  TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);
  /* Output Compare Timing Mode configuration: Channel2 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
  //這個(gè)是將CCR2_Val的值送到TMI2_CCR2中
  TIM_OC2Init(TIM2, &TIM_OCInitStructure);
  TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);
  /* Output Compare Timing Mode configuration: Channel3 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
  TIM_OC3Init(TIM2, &TIM_OCInitStructure);
  TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable);
  /*
  */
  /* Output Compare Timing Mode configuration: Channel4 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
  TIM_OC4Init(TIM2, &TIM_OCInitStructure);
  TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Disable);
  /* TIM IT enable */
  TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
  對(duì)DIER寄存器操作,中斷允許配置,相關(guān)代碼如下:
  
  而DIER寄存器如下:
  
  /* TIM2 enable counter */
  TIM_Cmd(TIM2, ENABLE);
  //開啟定時(shí)器的運(yùn)行
  while (1);
  }
 解讀:
 ?。?) 時(shí)鐘來源 CK_INT,設(shè)置的方法是讓TIMx_SMCR中的SMS[2:0]=000,最后通過TIM_Cmd(TIM2, ENABLE);函數(shù)將TIMx_CR1中的CEN置1,開啟定時(shí)器的運(yùn)行;
  (2) 接下來設(shè)置定時(shí)器的基本參數(shù)
 ?。?) 然后是設(shè)置定時(shí)器的各個(gè)通道
  (4) 最后開啟定時(shí)器運(yùn)行
  最后,將這個(gè)例子稍加修改,令其運(yùn)行在我的實(shí)驗(yàn)板上。
  需要修改的僅是將其原來的輸出從GPIOC的第6~第9腳變?yōu)镚PIOD的第8~第11腳。為此,需要改的地方有:
  
  將藍(lán)色框內(nèi)的GPIOC改為GPIOD。這個(gè)是最先寫的,但實(shí)際上一開始根本沒注意到這個(gè)地方,沒有改成GPIOD,結(jié)果一仿真,不正確,再一細(xì)查,原來端口還要配置時(shí)鐘,改過來就對(duì)了。瞧,這不驗(yàn)證了上面的說法“認(rèn)識(shí)事物是螺旋式上升的”學(xué)了定時(shí)器,對(duì)于I/O口和時(shí)鐘又有了更進(jìn)一步的理解了。
  
  將紅色框內(nèi)的GPIO分別改成8,9,10,11,將藍(lán)色框內(nèi)的GPIOC改為GPIOD。
  最后,到stm32f10x_it.c中,修改相應(yīng)的輸出
  
  參考上圖紅色框內(nèi),將GPIOC改為GPIOD,將6腳改為8腳,其他部分類推。
  修改好后運(yùn)行,所有燈亮了,看不出效果,于是又將預(yù)分頻系數(shù)由4改為64,這樣一來,LED開始閃爍了。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

慕尼黑2025年9月8日 /美通社/ -- 2025年9月8日德國國際汽車及智慧出行博覽會(huì)(IAA MOBILITY)于慕尼黑開幕,廣汽攜旗下五款新能源明星車型亮相,正式發(fā)布未來移動(dòng)出行的"廣汽方案"...

關(guān)鍵字: 廣汽 IO AI 移動(dòng)

上海2025年9月1日 /美通社/ -- 8月29日,由國際獨(dú)立第三方檢測(cè)、檢驗(yàn)和認(rèn)證機(jī)構(gòu)德國萊茵TÜV大中華區(qū)(簡稱"TÜV萊茵")...

關(guān)鍵字: 工程師 REGULATION 基礎(chǔ)知識(shí) 智能化

北京2025年8月19日 /美通社/ -- 美通社(PR Newswire)母公司,全球消費(fèi)者與媒體情報(bào)領(lǐng)軍企業(yè)Cision今日正式宣布,旗下CisionOne平臺(tái)連續(xù)第二年榮獲市場(chǎng)情報(bào)權(quán)威機(jī)構(gòu)MarTech Break...

關(guān)鍵字: CIS THROUGH TE IO

加州圣地亞哥和北京2025年7月25日 /美通社/ -- CreateAI(OTC:TSPH)今日宣布,公司與枕刀歌動(dòng)畫團(tuán)隊(duì)聯(lián)合出品的《繡春刀》短片在Collision Awards中一舉斬獲三枚金獎(jiǎng)和一枚銀獎(jiǎng),與Wal...

關(guān)鍵字: CREATE AI SI IO

上海 2025年7月4日 /美通社/ -- 本文闡述了汽車電子架構(gòu)從分布式向集中化演進(jìn)的趨勢(shì),黑芝麻智能分析了集中化帶來的安全隔離、實(shí)時(shí)性等關(guān)鍵挑戰(zhàn),并指出車用虛擬化技術(shù)是實(shí)現(xiàn)域控融合的核心解決方案。該技術(shù)能...

關(guān)鍵字: 虛擬化技術(shù) ECU 電子電氣 IO

深圳 2025年7月3日 /美通社/ -- 2025 年 7 月 2 日,晶泰科技(2228.HK)宣布完成對(duì)生成式 AI 蛋白設(shè)計(jì)賦能抗衰產(chǎn)品與藥物研發(fā)的技術(shù)平臺(tái) Fou...

關(guān)鍵字: FOUNDRY MIT 泰科 IO

新加坡 2025年6月11日 /美通社/ -- 在近日由新加坡資訊通信媒體發(fā)展局(IMDA)主辦的2025年新加坡亞洲科技大會(huì)(ATxSG)核心活動(dòng)—亞洲科技峰會(huì)(ATxS...

關(guān)鍵字: 新加坡 IO 生成式AI ST

香港 2025年5月30日 /美通社/ -- 建造業(yè)議會(huì)“未來建造中心”昨日正式開幕,標(biāo)志著香港建造業(yè)寫下數(shù)碼化發(fā)展的重要里程碑。開幕典禮假香港建造學(xué)院-九龍灣院校舉行,由發(fā)展局項(xiàng)目策略及管控處處長羅國權(quán)工程師、建造業(yè)...

關(guān)鍵字: 工程師 人工智能 數(shù)碼 模擬

香港 2025年5月30日 /美通社/ -- 建造業(yè)議會(huì)“未來建造中心”昨日正式開幕,標(biāo)志著香港建造業(yè)寫下數(shù)碼化發(fā)展的重要里程碑。開幕典禮今早假香港建造學(xué)院-九龍灣院校舉行,由發(fā)展局項(xiàng)目策略及管控處處長羅國權(quán)工程師、建...

關(guān)鍵字: 工程師 人工智能 數(shù)碼 模擬

蘇州 2025年5月27日 /美通社/ -- 5月24日-26日,第26屆全國醫(yī)院建設(shè)大會(huì)暨國際醫(yī)院建設(shè)、裝備及管理展覽會(huì)(CHCC 2025)在武漢舉行。藝卓(EIZO)攜手術(shù)室視覺顯示解決方案參展,以科技...

關(guān)鍵字: HC 醫(yī)學(xué)影像 IO 觸摸屏
關(guān)閉