发新帖我要提问
12
返回列表
打印
[其他ST产品]

systick定时器工作原理_数字压力表参数设置

[复制链接]
楼主: 自动化陈稳
手机看帖
扫描二维码
随时随地手机跟帖
21
自动化陈稳|  楼主 | 2023-2-28 01:29 | 只看该作者 回帖奖励 |倒序浏览
5.2.1 IO 口的位操作实现

该部分代码在 sys.h 文件中,实现对 STM32F1 各个 IO 口的位操作,包括读入和输出。当

然在这些函数调用之前,必须先进行 IO 口时钟的使能和 IO 口功能定义。此部分仅仅对 IO 口

进行输入输出读取和控制。

使用特权

评论回复
22
自动化陈稳|  楼主 | 2023-2-28 01:29 | 只看该作者
位带操作简单的说,就是把每个比特膨胀为一个 32 位的字,当访问这些字的时候就达到了

访问比特的目的,比如说 BSRR 寄存器有 32 个位,那么可以映射到 32 个地址上,我们去访问

这 32 个地址就达到访问 32 个比特的目的。这样我们往某个地址写 1 就达到往对应比特位写 1

的目的,同样往某个地址写 0 就达到往对应的比特位写 0 的目的。

我们往 Address0 地址写入 1,那么就可以达到往寄存器的 0 位 Bit0 赋值 1 的

目的。这里我们不想讲得过于复杂,因为位带操作在实际开发中可能只是用来 IO 口的输入输

出还比较方便,其他操作在日常开发中也基本很少用。下面我们看看 sys.h 中位带操作的定义。

使用特权

评论回复
23
自动化陈稳|  楼主 | 2023-2-28 01:29 | 只看该作者
代码如下:
#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 (GPIOA_BASE+12) //0x4001080C

#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C

#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C

#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C

#define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C

#define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C

#define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C

#define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808

#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08

#define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008

#define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408

#define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808

#define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08

#define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08

//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 PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出

#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入

#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出

#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入

使用特权

评论回复
24
自动化陈稳|  楼主 | 2023-2-28 01:29 | 只看该作者
以上代码的便是 GPIO 位带操作的具体实现,位带操作的详细说明,在权威指南中有详细

讲解,请参考<<CM3 权威指南>>五章(87 页~92 页)。比如说,我们调用 PAout(1)=1 是设置了

GPIOA 的一个管脚 GPIOA.1 为 1,实际是设置了寄存器 ODR 的某个位,但是我们的定义中

可以跟踪过去看到却是通过计算访问了一个地址。上面一系列公式也就是计算 GPIO 的某个 io

口对应的位带区的地址了。

使用特权

评论回复
25
自动化陈稳|  楼主 | 2023-2-28 01:30 | 只看该作者
有了上面的代码,我们就可以像 51/R 一样操作 STM32 的 IO 口了。比如,我要 PORTA

的七个 IO 口输出 1,则可以使用 PAout(6)=1;即可实现。我要判断 PORTA 的 15 个位

是否等于 1,则可以使用 if(PAin(14)==1)…;就可以了。

使用特权

评论回复
26
自动化陈稳|  楼主 | 2023-2-28 01:30 | 只看该作者
这里顺便说一下,在 sys.h 中的还有个全局宏定义:

//0,不支持 ucos 1,支持 ucos

#define SYSTEM_SUPPORT_OS

0

//定义系统文件夹是否支持 UCOS

SYSTEM_SUPPORT_OS,这个宏定义用来定义 SYSTEM 文件夹是否支持 ucos,如果在 ucos

下面使用 SYSTEM 文件夹,那么设置这个值为 1 即可,否则设置为 0(默认)。

使用特权

评论回复
27
自动化陈稳|  楼主 | 2023-2-28 01:30 | 只看该作者
5.3 usart 文件夹介绍

usart 文件夹内包含了 usart.c 和 usart.h 两个文件。串口相关只是,我们将在九章讲解串

口实验的时候给大家详细讲解。本节我们只给大家讲解比较独立的 printf 函数支持相关的知识。

使用特权

评论回复
28
自动化陈稳|  楼主 | 2023-2-28 01:30 | 只看该作者
5.3.1 printf 函数支持

printf 函数支持的代码在 usart.c 文件的上方,在我们初始化和使能串口 1 之后,然后把

这段代码加入到工程,便可以通过 printf 函数向串口 1 发送我们需要的内容,方便开发过程中

查看代码执行情况以及一些变量值。这段代码如果要修改一般也只是用来改变 printf 函数针对

的串口号,大多情况我们都不需要修改。

使用特权

评论回复
29
自动化陈稳|  楼主 | 2023-2-28 01:30 | 只看该作者
代码内容如下:

//加入以下代码,支持 printf 函数,而不需要选择 use MicroLIB

#if 1

#pragma import(__use_no_semihosting)

//标准库需要的支持函数

struct __FILE

{

int handle;

};

FILE __stdout;

//定义_sys_exit()以避免使用半主机模式

void _sys_exit(int x)

{

x = x;

}

//重定义 fputc 函数

int fputc(int ch, FILE *f)

{

while((USART1->SR&0X40)==0);//循环发送,直到发送完毕

USART1->DR = (u8) ch;

return ch;

}

#endif

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则