STM8S 韌體庫GPIO設定問題
ST對STM8S系列都有提供韌體庫,而不同的版本自然存在一些不同,版本也一直從V1.0.0升級到目前的V1.1.1。
環境: FWLIB V1.0.1版本,採用STM8SF103
在使用GPIO庫時,一個偶然發現stm8s_gpio.h中的巨集定義是存在問題的。
程式碼定義如下:
我在main.c中是直接這樣用的 GPIO_Init(GPIOC,GPIO_PIN_ALL,GPIO_MODE_OUT_PP_HIGH_FAST); //將GPIOC所有IO口設定成推輓輸出,10M速度。空閒IO口設定為輸出低電平能降低不必要的功耗。****************************************************************************** * @file stm8s_gpio.h * @brief This file contains all functions prototype and macros for the GPIO peripheral. * @author STMicroelectronics - MCD Application Team * @version V1.0.1 * @date 09/22/2008 ****************************************************************************** /** * @brief GPIO modes * * Bits definitions: * - Bit 7: 0 = INPUT mode * 1 = OUTPUT mode * 1 = PULL-UP (input) or PUSH-PULL (output) * - Bit 5: 0 = No external interrupt (input) or No slope control (output) * 1 = External interrupt (input) or Slow control enabled (output) * - Bit 4: 0 = Low level (output) * 1 = High level (output push-pull) or HI-Z (output open-drain) */ typedef enum { GPIO_MODE_IN_FL_NO_IT = (u8)0b00000000, /*!< Input floating, no external interrupt */ GPIO_MODE_IN_PU_NO_IT = (u8)0b01000000, /*!< Input pull-up, no external interrupt */ GPIO_MODE_IN_FL_IT = (u8)0b00100000, /*!< Input floating, external interrupt */ GPIO_MODE_IN_PU_IT = (u8)0b01100000, /*!< Input pull-up, external interrupt */ GPIO_MODE_OUT_OD_LOW_FAST = (u8)0b10000000, /*!< Output open-drain, low level, no slope control */ GPIO_MODE_OUT_PP_LOW_FAST = (u8)0b11000000, /*!< Output push-pull, low level, no slope control */ GPIO_MODE_OUT_OD_LOW_SLOW = (u8)0b10100000, /*!< Output open-drain, low level, slow slope */ GPIO_MODE_OUT_PP_LOW_SLOW = (u8)0b11100000, /*!< Output push-pull, low level, slow slope */ GPIO_MODE_OUT_OD_HIZ_FAST = (u8)0b10010000, /*!< Output open-drain, high-impedance level, no slope control */ GPIO_MODE_OUT_PP_HIGH_FAST = (u8)0b11010000, /*!< Output push-pull, high level, no slope control */ GPIO_MODE_OUT_OD_HIZ_SLOW = (u8)0b10110000, /*!< Output open-drain, high-impedance level, slow slope */ GPIO_MODE_OUT_PP_HIGH_SLOW = (u8)0b11110000 /*!< Output push-pull, high level, slow slope */ }GPIO_Mode_TypeDef;
但是除錯檢視暫存器時發現 CR2暫存器全為0,不應該才對。手冊上清晰的表明了為1為設定10M速度。
翻看stm8s_gpio.c中的GPIO_Init函式,有設定CR2暫存器,前提是根據GPIO_MODE掩碼來進行判斷,判斷的根據就是 Bit 5。如下:
if ((((u8)(GPIO_Mode)) & (u8)0x20) != (u8)0x00) /* Interrupt or Slow slope */ { GPIOx->CR2 |= GPIO_Pin; } else /* No external interrupt or No slope control */ { GPIOx->CR2 &= (u8)(~(GPIO_Pin)); }
繼續檢視韌體庫,對於V1.1.1來說不存在這個問題,如:
****************************************************************************** * @file stm8s_gpio.h * @brief This file contains all functions prototype and macros for the GPIO peripheral. * @author STMicroelectronics - MCD Application Team * @version V1.1.1 * @date 06/05/2009 ****************************************************************************** /** * @brief GPIO modes * * Bits definitions: * - Bit 7: 0 = INPUT mode * 1 = OUTPUT mode * 1 = PULL-UP (input) or PUSH-PULL (output) * - Bit 5: 0 = No external interrupt (input) or No slope control (output) * 1 = External interrupt (input) or Slow control enabled (output) * - Bit 4: 0 = Low level (output) * 1 = High level (output push-pull) or HI-Z (output open-drain) */ typedef enum { GPIO_MODE_IN_FL_NO_IT = (u8)0b00000000, /*!< Input floating, no external interrupt */ GPIO_MODE_IN_PU_NO_IT = (u8)0b01000000, /*!< Input pull-up, no external interrupt */ GPIO_MODE_IN_FL_IT = (u8)0b00100000, /*!< Input floating, external interrupt */ GPIO_MODE_IN_PU_IT = (u8)0b01100000, /*!< Input pull-up, external interrupt */ GPIO_MODE_OUT_OD_LOW_FAST = (u8)0b10100000, /*!< Output open-drain, low level, 10MHz */ GPIO_MODE_OUT_PP_LOW_FAST = (u8)0b11100000, /*!< Output push-pull, low level, 10MHz */ GPIO_MODE_OUT_OD_LOW_SLOW = (u8)0b10000000, /*!< Output open-drain, low level, 2MHz */ GPIO_MODE_OUT_PP_LOW_SLOW = (u8)0b11000000, /*!< Output push-pull, low level, 2MHz */ GPIO_MODE_OUT_OD_HIZ_FAST = (u8)0b10110000, /*!< Output open-drain, high-impedance level,10MHz */ GPIO_MODE_OUT_PP_HIGH_FAST = (u8)0b11110000, /*!< Output push-pull, high level, 10MHz */ GPIO_MODE_OUT_OD_HIZ_SLOW = (u8)0b10010000, /*!< Output open-drain, high-impedance level, 2MHz */ GPIO_MODE_OUT_PP_HIGH_SLOW = (u8)0b11010000 /*!< Output push-pull, high level, 2MHz */ }GPIO_Mode_TypeDef;
同樣是GPIO_MODE_OUT_PP_HIGH_FAST,前者定義為 0b11010000,而後者則是 0b11110000。
後來從發行日志裡也瞭解到,ST已經更正了這個錯誤。
<h3>V1.1.1 - 06/05/2009</h3>
@code
General
-------
+ Project template updated for both STVD and RIDE toolchains
+ Almost peripheral examples reviewed and validated with both Cosmic and Raisonance
compilers
library
-------
+ stm8s.h:
- __CONST definition added for Cosmic and Raisonance compilers
- TINY definition added for Cosmic and Raisonance compilers
- NEAR definition added for Raisonance compilers
- CAN registers declaration updated
- ADC1 registers declaration updated
+ stm8s_adc1.h:
- IS_ADC1_BUFFER_OK macro definition updated
+ stm8s_beep.c:
- BEEP_Init function updated
- BEEP->CSR |= BEEP_CSR_BEEPEN; removed from init function
+ stm8s_can.c/.h:
- Private variables declaration changed to volatile
- CAN_DeInit function updated
- CAN_Receive function updated
- CAN_FilterInit funtion updated
- CAN_Transmit function updated
- CAN_IT_TypeDef enum updated:
- CAN_IT_ERR and CAN_IT_LEC definition updated to avoid ANSI check
error with Cosmic
+ stm8s_clk.h:
- CLK_Peripheral_TypeDef enum updated:
- CLK_PERIPHERAL_UART1 definition updated and conditioned by the
device to use
+ stm8s_gpio.h:
- The GPIO_Mode_TypeDef enum element definition updated:
- GPIO_MODE_OUT_OD_LOW_FAST
- GPIO_MODE_OUT_PP_LOW_FAST
- GPIO_MODE_OUT_OD_LOW_SLOW
- GPIO_MODE_OUT_PP_LOW_SLOW
- GPIO_MODE_OUT_OD_HIZ_FAST
- GPIO_MODE_OUT_PP_HIGH_FAST
- GPIO_MODE_OUT_OD_HIZ_SLOW
- GPIO_MODE_OUT_PP_HIGH_SLOW
使用FWLIB V1.1.1替換FWLIB V1.0.1過程中,需要注意新版本中不存在 stm8s_macro.h,stm8s_map.h,取而代之的是stm8s.h,而且stm8s.h中外設巨集配置也與舊版本不同。對於外設的編譯判斷舊版採用的是stm8s_conf.h檔案,而新版則是根據晶片的型號。
舊版: 在stm8s_map.h中進行編譯巨集條件判斷
#ifdef _ADC1
#define ADC1 ((ADC1_TypeDef *) ADC1_BaseAddress)
#endif
#ifdef _ADC2
#define ADC2 ((ADC2_TypeDef *) ADC2_BaseAddress)
#endif
#ifdef _ITC
#define ITC ((ITC_TypeDef *) ITC_BaseAddress)
#endif
#ifdef _CFG
#define CFG ((CFG_TypeDef *) CFG_BaseAddress)
#endif
.......
.......
新版: 在stm8s.h中進行巨集條件判斷
#if defined(STM8S105) || defined(STM8S103) || defined(STM8S903)
#define ADC1 ((ADC1_TypeDef *) ADC1_BaseAddress)
#endif /* (STM8S105) ||(STM8S103) || (STM8S903) */
#if defined(STM8S208) || defined(STM8S207)
#define ADC2 ((ADC2_TypeDef *) ADC2_BaseAddress)
#endif /* (STM8S208) ||(STM8S207) */
#define AWU ((AWU_TypeDef *) AWU_BaseAddress)
#define BEEP ((BEEP_TypeDef *) BEEP_BaseAddress)
#ifdef STM8S208
#define CAN ((CAN_TypeDef *) CAN_BaseAddress)
#endif /* (STM8S208) */
#define CLK ((CLK_TypeDef *) CLK_BaseAddress)
......
......
新版韌體庫無需使用stm8s_conf.h來配置外設,轉而是使用晶片的型號即可。如果使用了USE_STDPERIPH_DRIVER巨集,則仍然會包含stm8s_conf.h配置檔案。STM8S103,編譯過程中自然就能夠將ADC1等外設編譯進去。
還有要注意的就是,不存在的外設不要加入到專案中,這樣會導致編譯不過。
剔除了stm8s_adc2.c、stm8s_can.c、stm8s_tim3.c、stm8s_tim5.c、stm8s_tim6.c、stm8s_uart2.c、stm8s_uart3.c,這些外設對於STM8S103是不存在的。