STM32F407入门开发: 位带操作

发布时间:2023-09-04  

一、位带的文档介绍

STM32F407的位带操作可以实现类似51单片机中寄存器的操作方法,操作GPIO口代码简洁方便。 关于位段的操作在Cortex-M3M4权威指南里有详细描述:


支持位带操作后,可以使用普通的加载/存储指令来对单一的比特位进行读写。


在CM3位带区中,有两个区中实现了位带。 其中一个是 SRAM 区的最低 1MB 范围,第二个则是片内外设区的最低 1MB 范围。 这两个区中的地址除了可以像普通的 RAM 一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个 32 位的字。当你通过位带别名区访 问这些字时,就可以达到访问原始比特位的目的。


二、位带实现代码

Sys.c文件增加以下代码:


#define GPIOA_IDR (0x40020000+0x10)

#define GPIOA_ODR (0x40020000+0x14)

#define GPIOB_IDR (0x40020400+0x10)

#define GPIOB_ODR (0x40020400+0x14)

#define GPIOC_IDR (0x40020800+0x10)

#define GPIOC_ODR (0x40020800+0x14)

#define GPIOD_IDR (0x40020C00+0x10)

#define GPIOD_ODR (0x40020C00+0x14)

#define GPIOE_IDR (0x40021000+0x10)

#define GPIOE_ODR (0x40021000+0x14)

#define GPIOF_IDR (0x40021400+0x10)

#define GPIOF_ODR (0x40021400+0x14)

#define GPIOG_IDR (0x40021800+0x10)

#define GPIOG_ODR (0x40021800+0x14)

#define GPIOH_IDR (0x40021C00+0x10)

#define GPIOH_ODR (0x40021C00+0x14)


//把“位带地址+位序号”转换成别名地址的宏

#define BITBAND(addr,bitnum) ((addr&0xF0000000)+0x2000000+((addr&0xFFFFF)<<5)+(bitnum<<2))

//把该地址转换成一个指针

#define MEM_ADDR(addr) *((volatile unsigned long *) (addr))

#define PAout(x) MEM_ADDR(BITBAND(GPIOA_ODR,x))

#define PAin(x) MEM_ADDR(BITBAND(GPIOA_IDR,x))

#define PBout(x) MEM_ADDR(BITBAND(GPIOB_ODR,x))

#define PBin(x) MEM_ADDR(BITBAND(GPIOB_IDR,x))

#define PCout(x) MEM_ADDR(BITBAND(GPIOC_ODR,x))

#define PCin(x) MEM_ADDR(BITBAND(GPIOC_IDR,x))

#define PDout(x) MEM_ADDR(BITBAND(GPIOD_ODR,x))

#define PDin(x) MEM_ADDR(BITBAND(GPIOD_IDR,x))

#define PEout(x) MEM_ADDR(BITBAND(GPIOE_ODR,x))

#define PEin(x) MEM_ADDR(BITBAND(GPIOE_IDR,x))

#define PFout(x) MEM_ADDR(BITBAND(GPIOF_ODR,x))

#define PFin(x) MEM_ADDR(BITBAND(GPIOF_IDR,x))

#define PGout(x) MEM_ADDR(BITBAND(GPIOG_ODR,x))

#define PGin(x) MEM_ADDR(BITBAND(GPIOG_IDR,x))

#define PHin(x) MEM_ADDR(BITBAND(GPIOH_IDR,x))

#define PHout(x) MEM_ADDR(BITBAND(GPIOH_ODR,x))

复制代码

Led.h 增加位带操作代码

#define LED0 PFout(9)

#define LED1 PFout(10)

#define BEEP PFout(8)


复制代码

Key.h增加位带操作代码

#define KEY0  PEin(4)

#define KEY1  PEin(3)

#define KEY2  PEin(2)

#define KEY_UP PAin(0)


复制代码

Main.c示例代码

#include "stm32f4xx.h" // Device header

#include "led.h"

#include "delay.h"

#include "key.h"

#include "usart.h"

#include "sys.h"

int main(void)

{

u8 i,key;

LED_Init();

KEY_Init();

USART1_Init(84,115200);

while(1)

{

key=ScanKeyVal(0);

if(key)

{

i=!i;

LED0=!LED0;

LED1=!LED1;

}

}

}

复制代码

三、DS18B20温度传感器示例-位带控制实现时序

#include "ds18b20.h"

/*

函数功能: 硬件初始化--IO配置

硬件连接: PB15

*/

void DS18B20_Init(void)

{

    /*1. 开时钟*/

    RCC->APB2ENR|=1<<3; //PB

    /*2. 配置GPIO口模式*/

    GPIOB->CRH&=0x0FFFFFFF;

    GPIOB->CRH|=0x30000000;

    /*3. 上拉*/

    GPIOB->ODR|=1<<15;

}


/*

函数功能: 发送复位脉冲检测DS18B20硬件--建立通信过程

返 回 值: 0表示成功  1表示失败  

*/

u8 DS18B20_Check(void)

{

    u8 i;

    DS18B20_OUT_MODE(); //配置IO口为输出模式

    DS18B20_OUT=0;      //拉低

    delay_us(580);       

    DS18B20_OUT=1;      //拉高

    

    DS18B20_IN_MODE();  //配置IO口为输入模式

    for(i=0;i<100;i++)

    {

        if(DS18B20_IN==0)break;

        delay_us(1);

    }

    if(i==100)return 1;

    

    for(i=0;i<250;i++)

    {

       if(DS18B20_IN)break;

       delay_us(1); 

    }

    if(i==250)return 1;

    return 0;

}


/*

函数功能: DS18B20写一个字节数据

*/

void DS18B20_WriteOnebyte(u8 cmd)

{

    u8 i;

    DS18B20_OUT_MODE(); //输出模式

    for(i=0;i<8;i++)

    {

        if(cmd&0x01) //发送1

        {

            DS18B20_OUT=0;

            delay_us(15);

            DS18B20_OUT=1;

            delay_us(45);

            DS18B20_OUT=1;

            delay_us(2);

        }

        else //发送0

        {

            DS18B20_OUT=0;

            delay_us(15);

            DS18B20_OUT=0;

            delay_us(45);

            DS18B20_OUT=1;

            delay_us(2);

        }

        cmd>>=1;

    }

}


/*

函数功能: DS18B20读一个字节数据

*/

u8 DS18B20_ReadOnebyte(void)

{

    u8 i;

    u8 data=0;

    for(i=0;i<8;i++)

    {

        DS18B20_OUT_MODE(); //输出模式

        DS18B20_OUT=0;

        delay_us(2);

        DS18B20_IN_MODE();

        delay_us(8);

        data>>=1; //右移1位

        if(DS18B20_IN)data|=0x80;

        delay_us(50);

        DS18B20_OUT=1;

        delay_us(2);

    }

    return data;

}


/*

函数功能: 读取一次DS18B20的温度数据

返回值: 读取的温度数据高低位

*/

u16 DS18B20_ReadTemp(void)

{

   u16 temp;

   u8 t_L,t_H;

   if(DS18B20_Check())return 1;

   DS18B20_WriteOnebyte(0xCC); //跳跃 ROM 指令 --不验证身份

   DS18B20_WriteOnebyte(0x44); //发送温度转换指令

    

   if(DS18B20_Check())return 2;

   DS18B20_WriteOnebyte(0xCC); //跳跃 ROM 指令 --不验证身份

   DS18B20_WriteOnebyte(0xBE); //读取RAM里的数据

   

   //读取温度

   t_L=DS18B20_ReadOnebyte(); //低字节

   t_H=DS18B20_ReadOnebyte(); //高字节

   temp=t_H<<8|t_L;

   return temp; 

}


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>