LibOpenCM3(五) 基礎功能: 系統時鐘, GPIO, 定時器
阿新 • • 發佈:2022-02-24
LibOpenCM3 提供了快捷方法用於初始化系統時鐘, 方法所在檔案lib/stm32/f1/rcc.c, 對應板載晶振為8MHz, 需要設定為72MHz系統頻率的應用. 這個檔案下還提供了其它的快捷方法, 在最新的版本中, 原來的方法還能呼叫, 但是已經被標為**Deprecated**了, 編譯會產生warning提示. 需要改為下面的呼叫方式. GPIO的設定與SPL/HAL流程是一樣的, 只是函式名和常量名有些區別. 不同MCU型號, 能使用的定時器編號不一樣, 需要根據手冊確定, 下面以TIM2為例說明定時器的設定流程.
目錄
- LibOpenCM3(一) Linux下命令列開發環境配置
- LibOpenCM3(二) 專案模板 Makefile分析
- LibOpenCM3(三) .ld檔案(聯結器指令碼)和startup程式碼說明
- LibOpenCM3(四) VSCode IDE 環境配置
- LibOpenCM3(五) 基礎功能: 系統時鐘, GPIO, 定時器
LibOpenCM3 時鐘, RCC
LibOpenCM3 提供了快捷方法用於初始化系統時鐘
舊版本的系統時脈初始化
rcc_clock_setup_in_hse_8mhz_out_72mhz();
方法所在檔案lib/stm32/f1/rcc.c, 對應板載晶振為8MHz, 需要設定為72MHz系統頻率的應用. 這個檔案下還提供了其它的快捷方法
// 使用內部RC產生64MHz void rcc_clock_setup_in_hsi_out_64mhz(void) // 使用內部RC產生48MHz void rcc_clock_setup_in_hsi_out_48mhz(void) // 使用內部RC產生24MHz void rcc_clock_setup_in_hsi_out_24mhz(void) // 以下是使用外部晶振的方法 void rcc_clock_setup_in_hse_8mhz_out_24mhz(void) void rcc_clock_setup_in_hse_8mhz_out_72mhz(void) void rcc_clock_setup_in_hse_12mhz_out_72mhz(void) void rcc_clock_setup_in_hse_16mhz_out_72mhz(void) void rcc_clock_setup_in_hse_25mhz_out_72mhz(void)
使用時直接呼叫就可以了, 例如
int main(void)
{
rcc_clock_setup_in_hse_8mhz_out_72mhz();
gpio_setup();
tim_setup();
while (1)
{
//...
}
return 0;
}
非常方便
新版本的系統時脈初始化
在最新的版本中, 原來的方法還能呼叫, 但是已經被標為Deprecated了, 編譯會產生warning提示. 需要改為下面的呼叫方式
rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]);
定義的檔案位置沒變, 對應的頻率放到了引數裡
enum rcc_clock_hsi {
RCC_CLOCK_HSI_24MHZ,
RCC_CLOCK_HSI_48MHZ,
RCC_CLOCK_HSI_64MHZ,
RCC_CLOCK_HSI_END
};
enum rcc_clock_hse {
RCC_CLOCK_HSE12_72MHZ,
RCC_CLOCK_HSE16_72MHZ,
RCC_CLOCK_HSE25_72MHZ,
RCC_CLOCK_HSE8_24MHZ,
RCC_CLOCK_HSE8_72MHZ,
RCC_CLOCK_HSE_END
};
LibOpenCM3 GPIO
GPIO的設定與SPL/HAL流程是一樣的, 只是函式名和常量名有些區別.
開啟GPIO外設時鐘
rcc_periph_clock_enable(RCC_GPIOC);
設定GPIO模式
gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO8);
gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO9);
// 可以簡化為
gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO8 | GPIO9);
輸入輸出模式選項
- GPIO_MODE_INPUT (default) Digital input
- GPIO_MODE_OUTPUT Digital output
- GPIO_MODE_AF Alternate Function (requires defining which alternate function desired)
- GPIO_MODE_ANALOG Analog (for use with ADC or DAC capable GPIO)
上下拉電阻選項
- GPIO_PUPD_NONE (default) No internal pull-up or pull-down resistor
- GPIO_PUPD_PULLUP Internal pull-up resistor
- GPIO_PUPD_PULLDOWN Internal pull-down resistor
輸出模式設定
gpio_set_output_options(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_LOW, GPIO8);
gpio_set_output_options(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_LOW, GPIO9);
// 可以簡化為
gpio_set_output_options(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_LOW, GPIO8 | GPIO9);
輸出型別
- GPIO_OTYPER_PP (default) Push-pull “totem pole” output
- GPIO_OTYPER_OD Open-drain output
輸出速度
- GPIO_OSPEED_HIGH High output speed
- GPIO_OSPEED_MED Medium output speed
- GPIO_OSPEED_LOW (default) Low output speed
- GPIO_OSPEED_100MHZ Up to 100MHz output speed (equivalent to high)
- GPIO_OSPEED_50MHZ Up to 50MHz output speed
- GPIO_OSPEED_25MHZ Up to 25MHz output speed (equivalent to medium)
- GPIO_OSPEED_2MHZ Up to 2MHz output speed (equivalent to low)
設定狀態
GPIO 沒有開啟或者關閉的操作, 開啟時鐘後GPIO就處於工作狀態, 這時候可以設定輸出電平
gpio_set(GPIOC, GPIO8);
gpio_set(GPIOC, GPIO9);
// 可以簡化為
gpio_set(GPIOC, GPIO8 | GPIO9);
LibOpenCM3 定時器
不同MCU型號, 能使用的定時器編號不一樣, 需要根據手冊確定, 下面以TIM2為例說明定時器的設定流程
開啟TIM2外設時鐘
開啟TIM2時鐘
/* Enable TIM2 clock. */
rcc_periph_clock_enable(RCC_TIM2);
如果需要初始化(重置)
/* Reset TIM2 peripheral to defaults. */
rcc_periph_reset_pulse(RST_TIM2);
設定定時器工作模式
timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
引數一: 分頻係數
/* CKD[1:0]: Clock division */
#define TIM_CR1_CKD_CK_INT (0x0 << 8)
#define TIM_CR1_CKD_CK_INT_MUL_2 (0x1 << 8)
#define TIM_CR1_CKD_CK_INT_MUL_4 (0x2 << 8)
#define TIM_CR1_CKD_CK_INT_MASK (0x3 << 8)
引數二: 對齊方式
/* CMS[1:0]: Center-aligned mode selection */
/****************************************************************************/
/** @defgroup tim_x_cr1_cms TIMx_CR1 CMS[1:0]: Center-aligned Mode Selection
@{*/
#define TIM_CR1_CMS_EDGE (0x0 << 5)
#define TIM_CR1_CMS_CENTER_1 (0x1 << 5)
#define TIM_CR1_CMS_CENTER_2 (0x2 << 5)
#define TIM_CR1_CMS_CENTER_3 (0x3 << 5)
#define TIM_CR1_CMS_MASK (0x3 << 5)
引數三: 計數方向
/* DIR: Direction */
/****************************************************************************/
/** @defgroup tim_x_cr1_dir TIMx_CR1 DIR: Direction
@{*/
#define TIM_CR1_DIR_UP (0 << 4)
#define TIM_CR1_DIR_DOWN (1 << 4)
設定定時係數
// 禁用 preload
timer_disable_preload(TIM2);
// 迴圈模式
timer_continuous_mode(TIM2);
// 預分頻係數, 根據當前所在匯流排計算分頻後的週期
timer_set_prescaler(TIM2, 36000);
// 計數週期
timer_set_period(TIM2, 1000);
如果要設定中斷
/* Enable TIM2 interrupt. */
nvic_enable_irq(NVIC_TIM2_IRQ);
/* Enable Channel 1 compare interrupt to recalculate compare values */
timer_enable_irq(TIM2, TIM_DIER_CC1IE);
啟用(使能)TIM2
/* Counter enable. */
timer_enable_counter(TIM2);
完整例子
使用GPIO和定時器外設的例子, 參考 LibOpenCM3(一) Linux下命令列開發環境配置 中的演示示例