怎么对高八位或低八位写值而不影响其它位,还有怎样单独读取高八位或低八位的值((u8*)(&GPIOB-ODR))[0]=0xaa;写低八位g_io_tempvalue=((u8*)(&GPIOB-ODR))[1];读高八位写高八位GPIOB-CRH&=0X00000000;GPIOB-CRH|=0X33333333;GPIOB-ODR|=0XFF00;低八位也一样,做与或者或运算的时候就可以避免影响不想改变的位。读高八位:u8temp;temp=((GPIOB-IDR8)&0xff)读低八位:temp=((GPIOB-IDR&0xff)使用BSRR和BRR寄存器直接操作STM32的I/O端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位;GPIOE-ODR=((GPIOE-ODR&0xff00)|(uint16_t)(Newdata8));高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,unsignedcharldata;GPIOA_BSRR=((unsignedint)~ldata16)|ldata;如果ldata=0x34,这相当于设置:GPIOA_BSRR=0x00CB0034;先定义宏:#defineGPIO_SETLOWBITS(GPIOA,UINT8)GPIOA-ODR=((GPIOA-ODR)&0xFF00)+UINT8调用:GPIO_SETLOWBITS(GPIOA,0xaa);GPIO_SETLOWBITS(GPIOA,0x55);STM32GPIO寄存器ODRBSRRBRR使用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.****************************************************************************************************STM32中单独设置GPIO端口高8位/低8位的方法几天前刚接触stm32的时候,被单独操作IO口给弄糊涂了,现记录下,现在发现其实蛮简单的,只是刚开始的时候~~~stm32的IO端口都是16位的,如果要单独操作某高8位或低8位,则不是那么简单,先看两张BSRR/BRR寄存器的图:据官方数据手册上面说,这两个寄存器用于专门对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(A-G)的低8位为0x55(01010101B),那么对于BSRR这个32位寄存器来说:低16位应该置为0000000001010101,这个就等于0x55,置1使某位为1,置0的位不影响原来的值高16位应该置为0000000010101010,这个就等于~0x55(即取反)的结果,置1使某位为0,置0不影响原来的值这样,BSRR(高16位写1清零;低16位写1置位)寄存器的值就是:0000000010101010/0000000001010101{两部分的高8位均为0,所以不会影响到IO口的高8位;寄存器的高16位的低8位为写入值按位取反,实现要写入的8位数据值0处清零,低16位的低8位为写入值原值,实现要写入的8位数据值1处置位。}总结,以下的宏实现对某端口的低8位置数,不影响高8位:#defineGPIO_WriteLow(GPIOx,a)GPIOx-BSRR=(((uint32_t)(uint8_t)~(a))16)|((uint32_t)(uint8_t)(a))3、对高8位置数这个和单独对低8位置数其实是一样的,只是设置的位不一样罢了同样,要使高8位为0x55,那么:低16位应该置为0101010100000000高16位应该置为1010101000000000,同样是取反的结果;不影响低8位的数据这样,BSRR寄存器的值就是10101010000000000101010100000000,可以看出,其实它就是上面那个结果左移8位总结,以下的宏实现对某端口的高8位置数,不影响低8位:#defineIO_WriteHigh(GPIOx,a)GPIOx-BSRR=(((uint8_t)(uint8_t)~(a))24)|(((uint32_t)(uint8_t)(a))8)大家不用担心效率问题,上面那两个宏最终的结果就是GPIOx-BSRR=value的形式,所以担心是多余的