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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 11649|回復(fù): 3
打印 上一主題 下一主題
收起左側(cè)

GPIO_Init()函數(shù)詳解

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

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

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
//GPIO_Init()函數(shù)定義
{
  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
由此可以看出當(dāng)上式判斷為真時,即GPIO設(shè)定為輸出模式。則進行下步判斷。
  {

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

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


  if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
//判斷是否是設(shè)置CRL。
  {
tmpreg = GPIOx->CRL;
//首先將GPIOx_CRL的值賦予tmpreg。
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
//通過循環(huán)比較,確定管腳
    {
      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位(剛剛經(jīng)過pinpos向左位移過兩位)。即將CRL要處理的位置進行處理。
        tmpreg &= ~pinmask;
//將tmpreg的相應(yīng)位置置零!

        tmpreg |= (currentmode << pos);
//將剛剛設(shè)置好的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);
          }
//若為上下拉輸入。如上設(shè)置,較為簡單。
        }
      }
    }
    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 踩
回復(fù)

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 久久不卡| 亚洲黄色片免费观看 | 北条麻妃99精品青青久久主播 | 国产精品美女久久久久久免费 | 国产一区二区三区四区在线观看 | 999久久久久久久久 国产欧美在线观看 | 狠狠做深爱婷婷综合一区 | 黑人中文字幕一区二区三区 | 精品欧美一区二区在线观看欧美熟 | 国产精品久久久久久久久久99 | 一区二区三区亚洲视频 | 国产精品久久久久久久久久久免费看 | 欧美一区二区三区在线视频 | 九九九久久国产免费 | 欧美日韩三级 | 欧美精品久久久久 | 中文字幕精品一区久久久久 | 欧美不卡一区二区三区 | 一级黄色短片 | 九九九色| 午夜欧美a级理论片915影院 | 91国语清晰打电话对白 | 在线观看av不卡 | 精品国产一区二区三区久久久四川 | 国产一区二区在线视频 | 欧美日韩在线电影 | 国产91久久久久久 | 午夜精品久久久久久久久久久久 | 日韩av在线一区 | 国产精品久久久久久亚洲调教 | 久久亚洲一区二区 | 国产一区二区在线播放 | 日韩成人av在线播放 | 国产在线精品一区二区三区 | 亚洲人人 | 一区二区三区精品视频 | 久久久影院 | av网站在线播放 | 国产综合av | 免费黄色日本 | 国产日韩欧美中文 |