[其他ST产品] systick定时器工作原理_数字压力表参数设置

[复制链接]
7820|38
 楼主| 自动化陈稳 发表于 2023-2-28 01:29 | 显示全部楼层
5.2.1 IO 口的位操作实现

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

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

进行输入输出读取和控制。
 楼主| 自动化陈稳 发表于 2023-2-28 01:29 | 显示全部楼层
位带操作简单的说,就是把每个比特膨胀为一个 32 位的字,当访问这些字的时候就达到了

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

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

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

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

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

出还比较方便,其他操作在日常开发中也基本很少用。下面我们看看 sys.h 中位带操作的定义。
 楼主| 自动化陈稳 发表于 2023-2-28 01:29 | 显示全部楼层
代码如下:
  1. #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((

  2. addr &0xFFFFF)<<5)+(bitnum<<2))

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

  4. #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))

  5. //IO 口地址映射

  6. #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C

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

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

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

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

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

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

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

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

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

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

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

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

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

  20. //IO 口操作,只对单一的 IO 口!

  21. //确保 n 的值小于 16!

  22. #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出

  23. #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入

  24. #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出

  25. #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入

  26. #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出

  27. #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入

  28. #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出

  29. #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入

  30. #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出

  31. #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入

  32. #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出

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

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

  35. #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入
 楼主| 自动化陈稳 发表于 2023-2-28 01:29 | 显示全部楼层
以上代码的便是 GPIO 位带操作的具体实现,位带操作的详细说明,在权威指南中有详细

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

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

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

口对应的位带区的地址了。
 楼主| 自动化陈稳 发表于 2023-2-28 01:30 | 显示全部楼层
有了上面的代码,我们就可以像 51/R 一样操作 STM32 的 IO 口了。比如,我要 PORTA

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

是否等于 1,则可以使用 if(PAin(14)==1)…;就可以了。
 楼主| 自动化陈稳 发表于 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(默认)。
 楼主| 自动化陈稳 发表于 2023-2-28 01:30 | 显示全部楼层
5.3 usart 文件夹介绍

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

口实验的时候给大家详细讲解。本节我们只给大家讲解比较独立的 printf 函数支持相关的知识。
 楼主| 自动化陈稳 发表于 2023-2-28 01:30 | 显示全部楼层
5.3.1 printf 函数支持

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

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

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

的串口号,大多情况我们都不需要修改。
 楼主| 自动化陈稳 发表于 2023-2-28 01:30 | 显示全部楼层
  1. 代码内容如下:

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

  3. #if 1

  4. #pragma import(__use_no_semihosting)

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

  6. struct __FILE

  7. {

  8. int handle;

  9. };

  10. FILE __stdout;

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

  12. void _sys_exit(int x)

  13. {

  14. x = x;

  15. }

  16. //重定义 fputc 函数

  17. int fputc(int ch, FILE *f)

  18. {

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

  20. USART1->DR = (u8) ch;

  21. return ch;

  22. }

  23. #endif
Wordsworth 发表于 2024-5-6 07:05 | 显示全部楼层

从定时器为TIM2,从模式选择为门控模式,触发源选择ITR0,开启定时器2中断。
Clyde011 发表于 2024-5-6 08:08 | 显示全部楼层

根据实际需求选择用哪种方式
公羊子丹 发表于 2024-5-6 09:01 | 显示全部楼层

每条大电流的地线要短而宽
万图 发表于 2024-5-6 10:04 | 显示全部楼层

使能主从模式,触发事件选择为更新事件,不需要开启中断。
Uriah 发表于 2024-5-6 11:07 | 显示全部楼层

主从定时的方式占用CPU资源少
帛灿灿 发表于 2024-5-6 13:03 | 显示全部楼层

主定时器为TIM1,通道2配置为PWM输出
Bblythe 发表于 2024-5-6 14:06 | 显示全部楼层

中断计数的方式实现简
周半梅 发表于 2024-5-6 16:02 | 显示全部楼层

多个电容并联
Pulitzer 发表于 2024-5-6 17:05 | 显示全部楼层

都可以产生指定个数的PWM脉冲
童雨竹 发表于 2024-5-6 19:01 | 显示全部楼层

作为功率开关管和整流器的散热部分
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部