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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 11872|回復: 3
打印 上一主題 下一主題
收起左側

GPIO_Init()函數詳解

[復制鏈接]
跳轉到指定樓層
樓主
ID:79466 發表于 2015-5-20 02:28 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
函數目的:對GPIO進行初始化。
如果對寄存器操作GPIO有一定了解的話,對下面理解起來就比較簡單。
如果將GPIO口設置為輸出模式,要設置兩個寄存器,CRL與ODR。
CRL:規定了低8位GPIO的輸出輸入狀態模式。
ODR:只用[15:0]確定GPIO端口的輸出值。
如下重點要理解CRL的工作方式。

CRL設置原理如上:
例如設置端口PD7,那么就需要設置[31:28]四位,首先確定輸入低二位輸入輸出狀態及輸出模式下的速度,高二位設置GPIO端口的工作方式。如果不理解,多看看兩幅原理圖。
編寫GPIO_Init()的原理(以CRL為例):
1.首先對GPIO_Mode,GPIO_Pin,GPIO_Speed進行宏定義。與CRL中使用略有差異,對GPIO_Mode中的定義,可以看到輸出模式下的定義的高四位均為0x1.而輸入模式下設置為0/2/4,此舉的目的是為了便于計算機進行識別處理。進行完第一步后,能夠的得到4位的GPIO的狀態的數據。
2.管腳及管腳的輸出值如何確定。這是GPIO_Init()的第二個難點。
首先確定GPIO_Pin是哪個管腳,然后確定后,將CRL寄存器的4*Pin的位置上的數據值為零,然后將第一步的取得值賦予CRL。
3.CRH和CRL的原理相同,通過 if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)來判斷是設置GPIO的低8位和高8位。

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
//GPIO_Init()函數定義
{
  uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
  uint32_t tmpreg = 0x00, pinmask = 0x00;
//定義變量用作GPIO中CRL、CRH、ODR的判定

  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));  
  //檢查實參是否符合要求

  currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
//將GPIO_Mode的值與0x0f相與,只取Mode的低四位將值賦予currentmode。
  if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
//說明是輸出。需要對速度進行配置。
// 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
由此可以看出當上式判斷為真時,即GPIO設定為輸出模式。則進行下步判斷。
  {

assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
//判斷GPIO_Speed的速度值是否符合要求

currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
//若為輸出,將速度配置到最后兩位。
//注意:因為GPIO_Mode設置的值得低二位均為零,所以將GPIO_Speed賦予currentmode。
  }


  if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
//判斷是否是設置CRL。
  {
tmpreg = GPIOx->CRL;
//首先將GPIOx_CRL的值賦予tmpreg。
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
//通過循環比較,確定管腳
    {
      pos = ((uint32_t)0x01) << pinpos;
//位移操作,簡單好用

      currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
//   將定義的GPIO_Pin與pos相與,如同下句,對管腳定位
      if (currentpin == pos)
//如果管腳確定為第pos個管腳。
      {
        pos = pinpos << 2;
//那么就將pinpos的向左位移兩位。即理解為位置乘以4.這需要看下CRL寄存器原理

        pinmask = ((uint32_t)0x0F) << pos;
//將0x0f(1111)向左位移pos位(剛剛經過pinpos向左位移過兩位)。即將CRL要處理的位置進行處理。
        tmpreg &= ~pinmask;
//將tmpreg的相應位置置零!

        tmpreg |= (currentmode << pos);
//將剛剛設置好的currentmode放置到指定的位置(原理參照CRL)。

        if (GPIO_InitStruct->GPIO  _Mode == GPIO_Mode_IPD)
        {
          GPIOx->BRR = (((uint32_t)0x01) << pinpos);
        }
        else
        {

          if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
          {
            GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
          }
//若為上下拉輸入。如上設置,較為簡單。
        }
      }
    }
    GPIOx->CRL = tmpreg;
  }


  if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
  {
    tmpreg = GPIOx->CRH;
    for (pinpos = 0x00; pinpos < 0x08; pinpos++)
    {
      pos = (((uint32_t)0x01) << (pinpos + 0x08));

      currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
      if (currentpin == pos)
      {
        pos = pinpos << 2;

        pinmask = ((uint32_t)0x0F) << pos;
        tmpreg &= ~pinmask;

        tmpreg |= (currentmode << pos);

        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
        {
          GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
        }

        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
        {
          GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
        }
      }
    }
    GPIOx->CRH = tmpreg;
  }
}

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏5 分享淘帖 頂2 踩
回復

使用道具 舉報

沙發
ID:871292 發表于 2022-9-6 21:48 | 只看該作者
好,分析得很詳細,謝謝!
回復

使用道具 舉報

板凳
ID:728915 發表于 2022-12-17 11:49 | 只看該作者
樓主辛苦了,剛好想做一個基于寄存器的IO口初始化函數,便于不同IO口的快速操作。,
回復

使用道具 舉報

地板
ID:1093869 發表于 2023-10-11 11:54 | 只看該作者
很詳細
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩成人小视频 | 亚洲成人国产 | 国产激情综合 | 欧美亚洲在线观看 | 欧美国产视频 | 亚洲精品福利视频 | 97成人在线 | 成人免费视频一区二区 | 欧美在线激情 | 亚洲第一伊人 | 婷婷中文字幕 | 国产午夜在线观看 | 五月天精品 | 中文在线字幕观看 | 亚洲精品1区2区 | 一级片在线观看视频 | 天天干天天干天天操 | 欧美日韩国产激情 | 日韩欧美在线一区 | 亚洲国产片 | 中文一级片 | 日日干夜夜爽 | 欧美视频免费在线观看 | 亚洲 欧美 另类 综合 偷拍 | 亚洲成人免费在线观看 | 色综合久久88 | 中文字幕日韩视频 | a毛片大片| 一区二区三区在线免费观看 | 久久精品人人 | 69福利视频 | 91久久精品日日躁夜夜躁欧美 | 成人免费毛片网站 | 国产三级在线看 | 久久精品小视频 | 91国在线| 成年人视频免费看 | 国产一区不卡 | av一级在线 | 免费中文字幕日韩欧美 | 日韩欧美在线一区 |