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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 11817|回復: 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 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 91精品国产欧美一区二区成人 | 日韩精品福利 | 亚洲日本中文 | 久久久久亚洲精品 | 91九色婷婷 | 欧洲av在线 | 亚洲一区二区中文字幕在线观看 | 91高清在线视频 | 超碰成人在线观看 | 在线视频三区 | 亚洲精品一区二区三区蜜桃久 | 99精品国产一区二区三区 | 久久久精品网站 | 免费成人在线网站 | 狠狠操av | 国产日产久久高清欧美一区 | 色婷婷久久久久swag精品 | 毛片网站免费观看 | 欧美国产日韩在线观看 | 亚洲午夜在线 | 欧美在线一区二区视频 | 欧美日韩第一页 | 91久色| 亚洲第一在线 | 亚洲一区 中文字幕 | 一级毛片视频在线 | 日韩一区二区三区在线观看 | 日韩色在线 | 国产欧美在线播放 | 久久亚洲精品久久国产一区二区 | 国产精品久久久久久久7电影 | 欧美二区乱c黑人 | 国产性色视频 | 国产日韩一区二区 | 中文字幕1区 | 精品久久一区二区三区 | 欧美一区二区三区 | 日日操夜夜操天天操 | 91免费视频| 草久视频 | 久久精品网|