STM32學習---GPIO和RCC(流水燈學習)
因為實驗室課題的需要,需要學習stm32。之前本科時學過51微控制器,雖然stm32本質上來說也是用C對底層暫存器進行操作,但是硬體架構和底層設計的不同兩者還是有天壤之別。所以把自己當做新生,從0開始學習STM32。擺正心態,穩步前進!
所採用的開發板:正點原子MINI(實驗室直接拿,很方便);
參考書籍:STM32庫開發實戰指南 劉火良 楊森著(圖書館借,很方便,外加學長推薦);
其他資料:網路查詢。
————————————————————————————————————————————————————————
關於 KEIL5 開發環境配置和另外找時間寫。
————————————————————————————————————————————————————————
1.什麼是GPIO?
通俗理解就是I/O引腳。輸入輸出埠。
2.GPIO分組?
GPIO分為:從GPIOA->GPIOG 等不同的組。
每一個GPIOX組又有0-15共16個不同的引腳。
這些引腳在通過軟體操作時,不同0/1組合可以實現不同的功能。
3.我們需要對GPIO進行哪些操作?
(1)配置輸入/輸出;
(2)配置相應的模式;
(3)配置資料傳輸速度;
4.如何操作?
現在有三種操作方法:暫存器操作,庫函式操作,HAL庫操作。因為實際課題的需要,所以我需要學習的是標準庫函式操作。
配置暫存器的具體操作,參考官方的技術手冊。
typedef struct
{
uint16_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured.
This parameter can be any value of @ref GPIO_pins_define */
GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins.
This parameter can be a value of @ref GPIOSpeed_TypeDef */
GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins.
This parameter can be a value of @ref GPIOMode_TypeDef */
}GPIO_InitTypeDef;
//使用GPIO時,首先定義一個GPIO的結構體型別變數;
//然後選定需要操作的引腳,用GPIO結構體中的成員定義;
#define GPIO_Pin_0 ((uint16_t)0x0001) /*!< Pin 0 selected */
#define GPIO_Pin_1 ((uint16_t)0x0002) /*!< Pin 1 selected */
#define GPIO_Pin_2 ((uint16_t)0x0004) /*!< Pin 2 selected */
#define GPIO_Pin_3 ((uint16_t)0x0008) /*!< Pin 3 selected */
#define GPIO_Pin_4 ((uint16_t)0x0010) /*!< Pin 4 selected */
#define GPIO_Pin_5 ((uint16_t)0x0020) /*!< Pin 5 selected */
#define GPIO_Pin_6 ((uint16_t)0x0040) /*!< Pin 6 selected */
#define GPIO_Pin_7 ((uint16_t)0x0080) /*!< Pin 7 selected */
#define GPIO_Pin_8 ((uint16_t)0x0100) /*!< Pin 8 selected */
#define GPIO_Pin_9 ((uint16_t)0x0200) /*!< Pin 9 selected */
#define GPIO_Pin_10 ((uint16_t)0x0400) /*!< Pin 10 selected */
#define GPIO_Pin_11 ((uint16_t)0x0800) /*!< Pin 11 selected */
#define GPIO_Pin_12 ((uint16_t)0x1000) /*!< Pin 12 selected */
#define GPIO_Pin_13 ((uint16_t)0x2000) /*!< Pin 13 selected */
#define GPIO_Pin_14 ((uint16_t)0x4000) /*!< Pin 14 selected */
#define GPIO_Pin_15 ((uint16_t)0x8000) /*!< Pin 15 selected */
#define GPIO_Pin_All ((uint16_t)0xFFFF) /*!< All pins selected */
//然後設定傳輸速度和模式:
typedef enum
{ GPIO_Mode_AIN = 0x0,
GPIO_Mode_IN_FLOATING = 0x04,
GPIO_Mode_IPD = 0x28,
GPIO_Mode_IPU = 0x48,
GPIO_Mode_Out_OD = 0x14,
GPIO_Mode_Out_PP = 0x10,
GPIO_Mode_AF_OD = 0x1C,
GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;
typedef enum
{
GPIO_Speed_10MHz = 1,
GPIO_Speed_2MHz,
GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;
//控制I/O輸出高、低電平
GPIO_SetBits()控制輸出高電平;
GPIO_ResetBits()控制輸出低電平;
//輸入引數:
兩個引數:GPIOx,GPIO_Pin;
//再運用初始化庫函式---GPIO_Init()進行“啟用”
/*
輸入兩個引數:GPIO——TypeDef 和 GPIO_InitTypeDef 型指標;
GPIOx用於選擇A-G具體的埠;
GPIO_InitTypeDef 是上面定義的GPIO型結構體變數;
*/
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
uint32_t tmpreg = 0x00, pinmask = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));
/*---------------------------- GPIO Mode Configuration -----------------------*/
currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
{
/* Check the parameters */
assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
/* Output mode */
currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
}
/*---------------------------- GPIO CRL Configuration ------------------------*/
/* Configure the eight low port pins */
if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
{
tmpreg = GPIOx->CRL;
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
pos = ((uint32_t)0x01) << pinpos;
/* Get the port pins position */
currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
if (currentpin == pos)
{
pos = pinpos << 2;
/* Clear the corresponding low control register bits */
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
/* Write the mode configuration in the corresponding bits */
tmpreg |= (currentmode << pos);
/* Reset the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << pinpos);
}
else
{
/* Set the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
}
}
}
}
GPIOx->CRL = tmpreg;
}
//和其他的MCU不同的是,STM32在設定好GPIO的暫存器之後,STM32還應該開啟外設時鐘。
//呼叫RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx,ENABLE)函式;
/*
RCC_APB2Periph_GPIOx---->x表示從A->G的埠,需要啟用哪個就把x改成哪個;
開啟掛載在外設匯流排APB2上的引腳(埠);
掛載在其餘匯流排的埠由其他函式呼叫開啟,具體可參考檔案: stm32f10x_rcc.c
*/
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
void Delay(int count)
{
for(;count>0;count--);
}
int main(void)
{
GPIO_InitTypeDef GPIOx1,GPIOx2;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
GPIOx1.GPIO_Pin=GPIO_Pin_8;
GPIOx2.GPIO_Pin=GPIO_Pin_2;
GPIOx1.GPIO_Mode=GPIO_Mode_Out_PP;
GPIOx2.GPIO_Mode=GPIO_Mode_Out_PP;
GPIOx1.GPIO_Speed=3;
GPIOx2.GPIO_Speed=3;
GPIO_Init(GPIOA,&GPIOx1);
GPIO_Init(GPIOD,&GPIOx2);
//GPIO_SetBits(GPIOA,GPIO_Pin_8);
while(1){
Delay(10000000);
GPIO_SetBits(GPIOA,GPIO_Pin_8);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
Delay(10000000);
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
return(1);
}