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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 7856|回復(fù): 8
收起左側(cè)

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

[復(fù)制鏈接]
ID:313060 發(fā)表于 2019-3-8 12:20 | 顯示全部樓層 |閱讀模式
40黑幣
怎么給GPIO多個操作位不影響其他的;像GPIOE->ODR = dat<<5;
這樣會影響低五位。
請問有什么好的方法?

最佳答案

查看完整內(nèi)容

是不是應(yīng)該還有屏的頭文件*.h之類的,在里面定義了顯示方向
回復(fù)

使用道具 舉報

ID:10947 發(fā)表于 2019-3-8 12:20 | 顯示全部樓層
是不是應(yīng)該還有屏的頭文件*.h之類的,在里面定義了顯示方向
回復(fù)

使用道具 舉報

ID:330198 發(fā)表于 2019-3-9 11:30 | 顯示全部樓層
一位一位賦值
回復(fù)

使用道具 舉報

ID:248705 發(fā)表于 2019-3-10 17:38 | 顯示全部樓層
GPIOE->ODR| = (uint32_t)1<<5;應(yīng)該是這樣的吧
回復(fù)

使用道具 舉報

ID:138119 發(fā)表于 2019-3-11 15:52 | 顯示全部樓層
STM32的16位端口輸出8位數(shù)據(jù)方法

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
調(diào)用:

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


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


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


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

使用道具 舉報

ID:138119 發(fā)表于 2019-3-11 15:53 | 顯示全部樓層
用GPIOx_BSRR寄存器

BRy位寫0無影響寫1復(fù)位相應(yīng)bit位
BSy位寫0無影響寫1置位相應(yīng)bit位

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

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

如果ldata=0x34,這相當(dāng)于設(shè)置:
  GPIOA_BSRR=0x00CB0034;
回復(fù)

使用道具 舉報

ID:138119 發(fā)表于 2019-3-11 15:54 | 顯示全部樓層
據(jù)官方數(shù)據(jù)手冊上面說, 這兩個寄存器用于專門對ODR進(jìn)行原子操作的位操作, 都是在置1的時候?qū)δ澄挥杏绊?

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

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

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

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

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

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

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

2.對低8位置數(shù)

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

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

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

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

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

總結(jié), 以下的宏實現(xiàn)對某端口的低8位置數(shù), 不影響高8位:

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

這個和單獨(dú)對低8位置數(shù)其實是一樣的, 只是設(shè)置的位不一樣罷了

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

低16位應(yīng)該置為 0101 0101 0000 0000

高16位應(yīng)該置為 1010 1010 0000 0000, 同樣是取反的結(jié)果; 不影響低8位的數(shù)據(jù)

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

總結(jié), 以下的宏實現(xiàn)對某端口的高8位置數(shù), 不影響低8位:

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

使用道具 舉報

ID:138119 發(fā)表于 2019-3-11 15:55 | 顯示全部樓層
怎么對高八位或低八位寫值而不影響其它位,還有怎樣單獨(dú)讀取高八位或低八位的值?


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

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

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




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

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

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

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

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

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

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

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





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

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

上述要求可以這樣實現(xiàn):

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

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

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

當(dāng)然還可以一次完成對8位的操作:

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

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




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

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

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



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

比如希望快速地對GPIOE的位7進(jìn)行翻轉(zhuǎn),則可以:

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

如果使用常規(guī)'讀-改-寫'的方法:

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次操作,結(jié)果造成位7和位6的變化不同步!
  GPIOE->BSRR = 0x80;
  GPIOE->BRR = 0x40;

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

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

如果ldata=0x34,這相當(dāng)于設(shè)置:
  GPIOA_BSRR=0x00CB0034;

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

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


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


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

比如希望快速地對GPIOE的位7進(jìn)行翻轉(zhuǎn),則可以:

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

如果使用常規(guī)'讀-改-寫'的方法:

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次操作,結(jié)果造成位7和位6的變化不同步!
  GPIOE->BSRR = 0x80;
  GPIOE->BRR = 0x40;

規(guī)則:

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

的某位為'0',則對應(yīng)的I/O端口不變。

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

的某位為'0',則對應(yīng)的I/O端口不變。

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

某位為'0',則對應(yīng)的I/O端口不變。



例如:

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

  GPIOD->BSRR = 0x0C21;// 使用規(guī)則一



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

  GPIOD->BRR = 0xC00A;// 使用規(guī)則三



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

,也只需一行語句:

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

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

回復(fù)

使用道具 舉報

ID:142059 發(fā)表于 2019-3-11 20:41 來自手機(jī) | 顯示全部樓層
位或|了解一下
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 亚洲精品在线视频 | 波多野结衣精品在线 | 第一色在线 | 精品亚洲一区二区三区 | 久久高清免费视频 | 亚洲视频中文字幕 | 成人av免费 | 蜜桃黄网 | 日韩超碰| 中文字幕一区二区三区四区五区 | 日本黄色大片免费 | 久久精品欧美视频 | 日韩一区二区久久 | 久久男人| 国产一级在线观看 | 午夜影院在线观看视频 | 爱爱免费视频 | 天天干夜夜操 | 国产分类视频 | 日本三级视频 | 国产黄色av电影 | 亚洲精品福利视频 | 日本不卡免费新一二三区 | 亚洲精品v日韩精品 | 日韩爱爱网 | 男女羞羞视频免费 | 在线看av的网址 | 99久久久久久 | 欧美一区视频 | 国产精品久久 | cao在线 | 黄色一级免费 | 波多野结衣中文视频 | 国产精品国产亚洲精品看不卡15 | 久久久久久综合 | 国产欧美日韩一区二区三区在线观看 | 在线视频一区二区三区 | 日韩综合一区 | 亚洲成人一区二区三区 | 三级国产三级在线 | 亚洲va欧美va人人爽午夜 |