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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

怎么給STM32 GPIO多個操作不影響其他的?

[復制鏈接]
跳轉到指定樓層
樓主
ID:313060 發表于 2019-3-8 12:20 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
40黑幣
怎么給GPIO多個操作位不影響其他的;像GPIOE->ODR = dat<<5;
這樣會影響低五位。
請問有什么好的方法?

最佳答案

查看完整內容

是不是應該還有屏的頭文件*.h之類的,在里面定義了顯示方向
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:10947 發表于 2019-3-8 12:20 | 只看該作者
是不是應該還有屏的頭文件*.h之類的,在里面定義了顯示方向
回復

使用道具 舉報

板凳
ID:330198 發表于 2019-3-9 11:30 | 只看該作者
一位一位賦值
回復

使用道具 舉報

地板
ID:248705 發表于 2019-3-10 17:38 | 只看該作者
GPIOE->ODR| = (uint32_t)1<<5;應該是這樣的吧
回復

使用道具 舉報

5#
ID:138119 發表于 2019-3-11 15:52 | 只看該作者
STM32的16位端口輸出8位數據方法

u16 temp;
u8 yourdata;

temp=GPIOA->ODR&0xff00;
temp+=yourdata;
GPIOA->ODR=temp;

或者:GPIOA->ODR=GPIOA->ODR&0xff00+(u16)yourdata;


=======================================================





先定義宏:
#define  GPIO_SETLOWBITS(GPIOA,UINT8)       GPIOA->ODR = ((GPIOA->ODR)&0xFF00) + UINT8
調用:

GPIO_SETLOWBITS(GPIOA,0xaa);
GPIO_SETLOWBITS(GPIOA,0x55);


=====================================================


最通用的方法是讀-修改-寫


因為對于STM32,IO操作比寄存器操作慢得多,所以我常用這樣的寫法:
GPIOA->BSRR=data|((data^0xff)<<16);
回復

使用道具 舉報

6#
ID:138119 發表于 2019-3-11 15:53 | 只看該作者
用GPIOx_BSRR寄存器

BRy位寫0無影響寫1復位相應bit位
BSy位寫0無影響寫1置位相應bit位

例如要對PORTA口低8位送出D0-D7數據,而不觸及高8位的數據:

假定要送出D0-D7的數據變量為ldata,
  unsigned char ldata;
  GPIOA_BSRR = ((unsigned int)~ldata << 16) | ldata;

如果ldata=0x34,這相當于設置:
  GPIOA_BSRR=0x00CB0034;
回復

使用道具 舉報

7#
ID:138119 發表于 2019-3-11 15:54 | 只看該作者
據官方數據手冊上面說, 這兩個寄存器用于專門對ODR進行原子操作的位操作, 都是在置1的時候對某位有影響.

舉例說下怎么對IO端口賦值:

1.對高8位/低8位/全部清零

很明顯, 這個只需要操作BRR寄存器即可:

對高8位清零:GPIOA->BRR = 0xFF00

對低8位清零:GPIOA->BRR = 0x00FF

全部清零: GPIOA->BRR = 0xFFFF 或 GPIOA->ODR = 0x0000

當然了, 使用下面2,3的兩個宏也可以完全該清零操作~ stm32固件庫是不是應該加上這兩個宏/函數?

2.對低8位置數

涉及到置數, 這個就是操作BSRR寄存器了

比如要使端口A的低8位為 0x55 (01010101B), 那么對于BSRR這個32位寄存器來說:

低16位應該置為 0000 0000 0101 0101, 這個就等于 0x55, 置1使某位為1, 置0的位不影響原來的值

高16位應該置為 0000 0000 1010 1010, 這個就等于 ~0x55(即取反)的結果, 置1使某位為0, 置0不影響原來的值

這樣, BSRR寄存器的值就是 0000 0000 1010 1010 0000 0000 0101 0101, 兩部分的高8位均為0, 所以不會影響到IO口的高8位

總結, 以下的宏實現對某端口的低8位置數, 不影響高8位:

#define GPIO_WriteLow(GPIOx,a)    GPIOx->BSRR=(((uint32_t)(uint8_t)~(a))<<16)|((uint32_t)(uint8_t)(a))
3.對高8位置數

這個和單獨對低8位置數其實是一樣的, 只是設置的位不一樣罷了

同樣, 要使高8位為0x55, 那么:

低16位應該置為 0101 0101 0000 0000

高16位應該置為 1010 1010 0000 0000, 同樣是取反的結果; 不影響低8位的數據

這樣, BSRR寄存器的值就是 1010 1010 0000 0000 0101 0101 0000 0000, 可以看出, 其實它就是上面那個結果左移8位

總結, 以下的宏實現對某端口的高8位置數, 不影響低8位:

#define GPIO_WriteHigh(GPIOx,a)    GPIOx->BSRR=(((uint8_t)(uint8_t)~(a))<<24)|(((uint32_t)(uint8_t)(a))<<8)
大家不用擔心效率問題, 上面那兩個宏最終的結果就是 GPIOx->BSRR=value 的形式, 所以擔心是多余的
回復

使用道具 舉報

8#
ID:138119 發表于 2019-3-11 15:55 | 只看該作者
怎么對高八位或低八位寫值而不影響其它位,還有怎樣單獨讀取高八位或低八位的值?


((u8*)(&GPIOB->ODR))[0] = 0xaa;寫低八位

g_io_tempvalue = ((u8*)(&GPIOB->ODR))[1];讀高八位

=============================================




寫高八位  
GPIOB->CRH &= 0X00000000;  
GPIOB->CRH |= 0X33333333;  
GPIOB->ODR |= 0XFF00;  

低八位也一樣,做與或者或運算的時候就可以避免影響不想改變的位。  

讀高八位:  
u8 temp;  
temp = ((GPIOB->IDR>>8)&0xff)  
讀低八位  
temp = ((GPIOB->IDR&0xff)

====
使用BSRR和BRR寄存器直接操作STM32的I/O端口        發布時間:2009-11-12 12:39:27
技術類別:單片機         

STM32的每個GPIO端口都有兩個特別的寄存器,GPIOx_BSRR和GPIOx_BRR寄存器,通過這兩個寄存器可以直接對對應的GPIOx端口置'1'或置'0'。

GPIOx_BSRR的高16位中每一位對應端口x的每個位,對高16位中的某位置'1'則端口x的對應位被清'0';寄存器中的位置'0',則對它對應的位不起作用。

GPIOx_BSRR的低16位中每一位也對應端口x的每個位,對低16位中的某位置'1'則它對應的端口位被置'1';寄存器中的位置'0',則對它對應的端口不起作用。

簡單地說GPIOx_BSRR的高16位稱作清除寄存器,而GPIOx_BSRR的低16位稱作設置寄存器。另一個寄存器GPIOx_BRR只有低16位有效,與GPIOx_BSRR的高16位具有相同功能。





舉個例子說明如何使用這兩個寄存器和所體現的優勢。例如GPIOE的16個IO都被設置成輸出,而每次操作僅需要改變低8位的數據而保持高8位不變,假設新的8位數據在變量Newdata中,

這個要求可以通過操作這兩個寄存器實現,STM32的固件庫中有兩個函數GPIO_SetBits()和GPIO_ResetBits()使用了這兩個寄存器操作端口。

上述要求可以這樣實現:

GPIO_SetBits(GPIOE, Newdata & 0xff);
GPIO_ResetBits(GPIOE, (~Newdata & 0xff));

也可以直接操作這兩個寄存器:

GPIOE->BSRR = Newdata & 0xff;
GPIOE->BRR = ~Newdata & 0xff;

當然還可以一次完成對8位的操作:

GPIOE->BSRR = (Newdata & 0xff) | (~Newdata & 0xff)<<16;

從最后這個操作可以看出使用BSRR寄存器,可以實現8個端口位的同時修改操作。




//==============================================================================================
如果不是用BRR和BSRR寄存器,則上述要求就需要這樣實現:

GPIOE->ODR = GPIOE->ODR & 0xff00 | Newdata;  低8位 ; //更新低8位,高8位不變
GPIOE->ODR = ((GPIOE->ODR & 0xff00) | (uint16_t)(Newdata<<8)); 高8位//更新高8位,低8位不變

平時用的比較多.
//===================================================================================================



使用BRR和BSRR寄存器可以方便地快速地實現對端口某些特定位的操作,而不影響其它位的狀態。

比如希望快速地對GPIOE的位7進行翻轉,則可以:

GPIOE->BSRR = 0x80; // 置'1'
GPIOE->BRR = 0x80; // 置'0'

如果使用常規'讀-改-寫'的方法:

GPIOE->ODR = GPIOE->ODR | 0x80; // 置'1'
GPIOE->ODR = GPIOE->ODR & 0xFF7F; // 置'0'





有人問是否BSRR的高16位是多余的,請看下面這個例子:

假如你想在一個操作中對GPIOE的位7置'1',位6置'0',則使用BSRR非常方便:
  GPIOE->BSRR = 0x400080;

如果沒有BSRR的高16位,則要分2次操作,結果造成位7和位6的變化不同步!
  GPIOE->BSRR = 0x80;
  GPIOE->BRR = 0x40;

=========================================
例如要對PORTA口低8位送出D0-D7數據,而不觸及高8位的數據:

假定要送出D0-D7的數據變量為ldata,
  unsigned char ldata;
  GPIOA_BSRR = ((unsigned int)~ldata << 16) | ldata;

如果ldata=0x34,這相當于設置:
  GPIOA_BSRR=0x00CB0034;

===================================
先定義宏:
#define  GPIO_SETLOWBITS(GPIOA,UINT8)       GPIOA->ODR = ((GPIOA->ODR)&0xFF00) + UINT8
調用:

GPIO_SETLOWBITS(GPIOA,0xaa);
GPIO_SETLOWBITS(GPIOA,0x55);


=================================================
STM32 GPIO寄存器ODR BSRR BRR  


使用BRR和BSRR寄存器可以方便地快速地實現對端口某些特定位的操作,而不影響其它位的狀態。

比如希望快速地對GPIOE的位7進行翻轉,則可以:

GPIOE->BSRR = 0x80; // 置'1'
GPIOE->BRR = 0x80; // 置'0'

如果使用常規'讀-改-寫'的方法:

GPIOE->ODR = GPIOE->ODR | 0x80; // 置'1'
GPIOE->ODR = GPIOE->ODR & 0xFF7F; // 置'0'

有人問是否BSRR的高16位是多余的,請看下面這個例子:

假如你想在一個操作中對GPIOE的位7置'1',位6置'0',則使用BSRR非常方便:
  GPIOE->BSRR = 0x00400080;

如果沒有BSRR的高16位,則要分2次操作,結果造成位7和位6的變化不同步!
  GPIOE->BSRR = 0x80;
  GPIOE->BRR = 0x40;

規則:

一、置GPIOD->BSRR低16位的某位為'1',則對應的I/O端口置'1';而置GPIOD->BSRR低16位

的某位為'0',則對應的I/O端口不變。

二、置GPIOD->BSRR高16位的某位為'1',則對應的I/O端口置'0';而置GPIOD->BSRR高16位

的某位為'0',則對應的I/O端口不變。

三、置GPIOD->BRR低16位的某位為'1',則對應的I/O端口置'0';而置GPIOD->BRR低16位的

某位為'0',則對應的I/O端口不變。



例如:

1)要設置D0、D5、D10、D11為高,而保持其它I/O口不變,只需一行語句:

  GPIOD->BSRR = 0x0C21;// 使用規則一



2)要設置D1、D3、D14、D15為低,而保持其它I/O口不變,只需一行語句:

  GPIOD->BRR = 0xC00A;// 使用規則三



3)要同時設置D0、D5、D10、D11為高,設置D1、D3、D14、D15為低,而保持其它I/O口不變

,也只需一行語句:

  GPIOD->BSRR = 0xC00A0C21;// 使用規則一和規則二

如果中斷中要對IO口設置,最好使用BSRR和BRR操作,而不要用ODR .

回復

使用道具 舉報

9#
ID:142059 發表于 2019-3-11 20:41 來自手機 | 只看該作者
位或|了解一下
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲色图在线观看 | 亚洲精品久久久 | 午夜久久| 久久人 | 国产精品久久久久久久久久久免费看 | 国产伦精品一区二区三区高清 | www.xxxx欧美| 日韩三级电影一区二区 | 91在线免费视频 | 成人av片在线观看 | 亚洲综合婷婷 | 国内精品视频在线 | 婷婷五月色综合香五月 | av国产精品 | 日本精品一区二区三区在线观看视频 | 免费激情网站 | 亚洲一区 中文字幕 | 成人亚洲精品 | 日韩久久综合网 | 国产精品一区久久久 | www.国产.com| 一区视频 | 羞羞的视频在线观看 | 97在线观视频免费观看 | 日韩精品一区二区三区在线 | 天天干夜夜操 | 日韩成人在线播放 | 免费国产一区二区 | 玖玖精品 | 一级a毛片 | 国内精品视频免费观看 | 97国产精品 | 日韩在线免费视频 | 精品久久久网站 | 久久天堂 | 一区二区三区四区在线免费观看 | 久久的色 | 久久欧美高清二区三区 | 欧美精品片 | 亚洲欧美激情国产综合久久久 | 91在线精品秘密一区二区 |