一、实验要点
- 目的:测量最大反转速度
- 可以通过C语言直接操作寄存器的方式,但c语言会转成汇编,会受编译器的优化程度影响,所以直接使用汇编操作寄存器进一步优化反转速度。
- ODR、BRR、BSRR寄存器的含义,具体参考博文(GPIO 配置之ODR, BSRR, BRR 详解):https://blog.csdn.net/byhunpo/article/details/88996657?ops_request_misc=&request_id=&biz_id=102&utm_term=ODR%E3%80%81BRR%E3%80%81BSRR%E5%AF%84%E5%AD%98%E5%99%A8%E7%9A%84%E5%90%AB%E4%B9%89&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-1-88996657.142v63control_1,201v3control_2,213v2t3_control1&spm=1018.2226.3001.4187
- 各个外设的速度如何配置,速度不匹配就会看到输出波形不正常。波形不完整或者失真现象。普通GPIO低速,USART、CAN速度高。所以将 IO 口配置 到最高 72MHZ 高速时,波形将不完整。
二、代码部分
反转代码 main.c
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "oled.h"
#include <string.h>
#define RXBUFFERSIZE 256 //�????大接收字节数
#if 1
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
OLED_Init();
OLED_Clear();
OLED_ShowString(0, 2 , "666", 16);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
#if 0
//#pragma asm
//asm("speed_test PROC");
//asm("EXPORT speed_test");
asm("ldr R0, =0x40011000"); //PC口
asm("LDR R1, =0x2000");
asm("toggle:");
asm("STR R1,[R0,#0x10]"); //灭
asm("STR R1,[R0,#0x14]"); //亮
asm("B toggle");
//#pragma endasm
#elif 0
while (1)
{
GPIOC->BRR = 0x2000;
GPIOC->BSRR = 0x2000; //低
}
#elif 0
while(1)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
}
#elif 0
while(1)
{
GPIOC->BSRR = (((GPIOC->ODR) & GPIO_PIN_13) << 16u) | (~(GPIOC->ODR) & GPIO_PIN_13);
}
#elif 0
while(1)
{
GPIOD->ODR = 0xffff;
GPIOD->ODR = 0x0000;
}
#elif 0
while(1)
{
GPIOD->ODR |= 0x2000;
GPIOD->ODR &= 0xDfff;
}
#elif 0
while(1)
{
GPIOD->ODR |= 0x2000;
GPIOD->ODR &= ~0x2000;
}
#endif
}
注意:不同的编译、开发环境下用法格式有差别。
keil 下的可用汇编格式:
__asm("")
__asm()
具体参考博文(Stm32CubeIDE如何支持C汇编命令asm):https://blog.csdn.net/u014627020/article/details/117979759
以 IMX6ull 板子 实现点灯功能为例, 汇编驱动代码 led.s 如下:
**************************************************************/
.global _start /* 全局标号 */
/*
* 描述: _start函数,程序从此函数开始执行此函数完成时钟使能、
* GPIO初始化、最终控制GPIO输出低电平来点亮LED灯。
*/
_start:
/* 例程代码 */
/* 1、使能所有时钟 */
ldr r0, =0X020C4068 /* CCGR0 */
ldr r1, =0XFFFFFFFF
str r1, [r0]
ldr r0, =0X020C406C /* CCGR1 */
str r1, [r0]
ldr r0, =0X020C4070 /* CCGR2 */
str r1, [r0]
ldr r0, =0X020C4074 /* CCGR3 */
str r1, [r0]
ldr r0, =0X020C4078 /* CCGR4 */
str r1, [r0]
ldr r0, =0X020C407C /* CCGR5 */
str r1, [r0]
ldr r0, =0X020C4080 /* CCGR6 */
str r1, [r0]
/* 2、设置GPIO1_IO03复用为GPIO1_IO03 */
ldr r0, =0X020E0068 /* 将寄存器SW_MUX_GPIO1_IO03_BASE加载到r0中 */
ldr r1, =0X5 /* 设置寄存器SW_MUX_GPIO1_IO03_BASE的MUX_MODE为5 */
str r1,[r0]
/* 3、配置GPIO1_IO03的IO属性
*bit 16:0 HYS关闭
*bit [15:14]: 00 默认下拉
*bit [13]: 0 kepper功能
*bit [12]: 1 pull/keeper使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 110 R0/6驱动能力
*bit [0]: 0 低转换率
*/
ldr r0, =0X020E02F4 /*寄存器SW_PAD_GPIO1_IO03_BASE */
ldr r1, =0X10B0
str r1,[r0]
/* 4、设置GPIO1_IO03为输出 */
ldr r0, =0X0209C004 /*寄存器GPIO1_GDIR */
ldr r1, =0X0000008
str r1,[r0]
/* 5、打开LED0
* 设置GPIO1_IO03输出低电平
*/
ldr r0, =0X0209C000 /*寄存器GPIO1_DR */
ldr r1, =0
str r1,[r0]
/*
* 描述: loop死循环
*/
loop:
b loop
三、实验结果
实验现象:不仅可通过示波器观察波形,由于灯的亮度和有效电压有关,方波有效值=U峰值 / 2 x (1 - 占空比),小灯初始化就为亮的状态 ,经反转后灯亮度将变暗。
待完善部分,直接通过keil、stm32 Cube IDE 查看波形