本帖最后由 qjp1988113 于 2020-9-30 12:42 编辑  
 
今天测试下HC32F460的位段功能。由于官方没提供例程,该程序由正点原子STM32对应的程序修改。 
先来看下华大手册的官方描述: 
 
 
写的比较简单,也未给出详细的具体操作说明。 
下面给出STM32关于位段操作的说明,含地址对应公式: 
 
 
 
 
我们参考M3编程手册--《Cortex M3权威指南》里面的位段说明,因为它是中文版本。 
 
 
很明显位段的功能,就是把外设寄存器BIT位的操作控制等效为一个32为地址寄存器的操作。 
我们往这个地址写读均能得到对应外设寄存器BIT位等效的回应。当然这个等效的寄存器地址 
跟外设是有一定关联的。 
再具体大家可以去看上面的那本书。 
华大HC32F460的例程里面对于寄存器的定义划分和ST还是有差异的,我们查找手册(我们这里仅仅做IO输出输入的控制): 
 
 
 
 
 
 
有这3个寄存器的明细,我们就可以开始了: 
//periBitBand         0X42000000 ~0X43FFFFFF  32M 
//GPIO  0X40053800 ~0X40053FFF  1K 
 
#define GPIO_BASE       (0x40053800ul) 
//位带操作,实现51类似的GPIO控制功能 
//IO口操作宏定义 
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))  
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))  
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum))  
//IO口地址映射 
#define GPIOA_ODR_Addr    (GPIO_BASE+0X04+0X10*0) //0x40020014 
#define GPIOB_ODR_Addr    (GPIO_BASE+0X04+0X10*1) //0x40020414  
#define GPIOC_ODR_Addr    (GPIO_BASE+0X04+0X10*2) //0x40020814  
#define GPIOD_ODR_Addr    (GPIO_BASE+0X04+0X10*3) //0x40020C14  
#define GPIOE_ODR_Addr    (GPIO_BASE+0X04+0X10*4) //0x40021014    
#define GPIOH_ODR_Addr    (GPIO_BASE+0X04+0X10*5) //0x40021C14     
 
 
#define GPIOA_IDR_Addr    (GPIO_BASE+0x00+0X10*0) //0x40020010  
#define GPIOB_IDR_Addr    (GPIO_BASE+0x00+0X10*1) //0x40020410  
#define GPIOC_IDR_Addr    (GPIO_BASE+0x00+0X10*2) //0x40020810  
#define GPIOD_IDR_Addr    (GPIO_BASE+0x00+0X10*3) //0x40020C10  
#define GPIOE_IDR_Addr    (GPIO_BASE+0x00+0X10*4) //0x40021010  
#define GPIOH_IDR_Addr    (GPIO_BASE+0x00+0X10*5) //0x40021C10  
 
 
//IO口操作,只对单一的IO口! 
//确保n的值小于16! 
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出  
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入  
 
#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出  
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入  
 
#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出  
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入  
 
#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出  
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入  
 
#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出  
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入 
 
#define PHout(n)   BIT_ADDR(GPIOH_ODR_Addr,n)  //输出  
#define PHin(n)    BIT_ADDR(GPIOH_IDR_Addr,n)  //输入 
 
在加入上诉定义之后后,我们就可以使用了。 
我们定义: 
//IO输出 
#define  LED0   PEout(6) 
#define  LED1   PAout(7) 
#define  LED2   PBout(5) 
#define  LED3   PBout(9) 
 
 
//IO输入 
#define KEY0                 PDin(3)           //PD3 
#define KEY1                 PDin(4)                //PD4  
#define KEY2                 PDin(5)                //PD5 
#define KEY3                 PDin(6)                //PD6 
 
 
当然IO口的初始化程序要另写。 
//按键扫描程序: 
uint8_t KEY_Scan(uint8_t mode)                  //按键扫描函数 
{ 
        static uint8_t key_up=1;//按键按松开标志 
        if(mode)key_up=1;  //支持连按                   
        if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==0)) 
        { 
                delay_ms(10);//去抖动  
                key_up=0; 
                if(KEY0==0)return 1; 
                else if(KEY1==0)return 2; 
                else if(KEY2==0)return 3; 
                else if(KEY3==0)return 4; 
        }else if(KEY0==1&&KEY1==1&&KEY2==1&&KEY3==1)key_up=1;              
         return 0;// 无按键按下 
} 
 
 
main函数里面的调用: 
key=KEY_Scan(0);                //得到键值 
if(key) 
{                                                    
        switch(key) 
        {                                  
                case KEY0_PRES:        //控制LED0翻转 
                        LED0=!LED0; 
                        break; 
                case KEY1_PRES:        //控制LED1翻转          
                        LED1=!LED1; 
                        break; 
                case KEY2_PRES:        //控制LED2翻转  
                        LED2=!LED2; 
                        break; 
                case KEY3_PRES:        //控制LED3翻转  
                        LED3=!LED3; 
                        break; 
        } 
}else delay_ms(10); 
 
编译下载,具体现象: 
 
 
 
好了,今天就到这! 
 
 
 
 
 
 
 |   
     
  
 |