当前位置: 首页 > news >正文

ARM - LED灯实验(cortex A7核/cortex M4核)

开发板:华清远见FSMP1A

主板:

 扩展板:

芯片:STM32MP157A

架构:ARMV7

内核:Cortex®-A7 650 MHz *2 + Cortex®-M4 MPU

串口工具:SecureCRT.exe

分析硬件电路图

(1)分析LED灯工作原理

LED灯电路图及拓展接口电路图:

 LED灯原理图:

通过电路图分析可知LD1\LD2\LD3工作原理 

1.PE10/PF10/PE8引脚写高电平,灯点亮 

2.PE10/PF10/PE8引脚写低电平,灯熄灭

(2)分析芯片框图

1.A7核执行程序如何控制GPIO控制器?
    汇编指令:ldr/str
    通过特殊功能寄存器,向特殊功能寄存器中写入指定的值,或者读取里面的内容

2.软件编程控制硬件的思想?
    通过特殊功能寄存器,向特殊功能寄存器中写入指定的值,或者读取里面的内容。控制相应的外设工作

3.什么是特殊功能寄存器?
    特殊功能寄存器是内存一块寻址空间
    芯片厂家出厂的时候,对这块空间做了特殊的用途,不可以作为普通的寄存器使用

4.通过以上框图进行分析,需要分析芯片手册哪几个章节?
    GPIO章节(13章节General-purpose I/Os )
    RCC章节(10章节Reset and clock control)

(3)分析手册RCC章节

分析RCC_MP_AHB4ENSETR 使AHB4总线使能

RCC_MP_AHB4ENSETR地址=基地址+偏移地址 = 0x50000000 + 0xA28 = 0x50000A28

RCC_MP_AHB4ENSETR[4] = 1 -------->设置GPIOE控制器使能工作


如何确定基地址

 

(4)分析手册GPIO章节

通过这个章节分析可知:GPIOx_MODER,GPIOx_OTYPER, GPIOx_OSPEEDR, GPIOx_PUPDR作用

1) GPIOx_MODER:GPIO模式寄存器----->设置为输出模式
2) GPIOx_OTYPER:GPIO输出类型寄存器----->设置为推挽/开漏输出
3) GPIOx_OSPEEDR:GPIO输出速度寄存器----->设置为输出速率
4) GPIOx_PUPDR:GPIO是否需要上下拉电阻
5) GPIOx_ODR:GPIO输出数据寄存器------>输出高低电平,实现LED灯点亮核熄灭

1) 分析GPIOx_MODER寄存器

LED1------>PE10引脚分析
1.如何确定GPIOE_MODER寄存器的地址?
    地址=基地址+偏移地址=0x50006000+0x00=0x50006000    
2.通过GPIOE_MODER设置PE10引脚设置为输出模式?
    GPIOE_MODER[21:20]=01------>输出模式
    向0x50006000地址中的第[21:20]写入01

2) 分析GPIOx_OTYPER寄存器

LED1------>PE10引脚分析
1.如何确定GPIOE_OTYPER寄存器的地址?
    地址=基地址+偏移地址=0x50006000+0x04=0x50006004  
2.通过GPIOE_OTYPER设置PE10引脚设置为推挽输出模式?
     GPIOE_OTYPER[10] = 0 ----->设置为推挽输出模式
     向0x50006004地址中的第[0]写入0

推挽输出:
        PMOS管和NMOS管都可以正常工作,可以输出高低电平

开漏输出:
        只有NMOS管可以正常工作,只可以输出低电平,如果想输出高电平,需要外接上拉电阻

3) 分析GPIOx_OSPEEDR寄存器

LED1------>PE10引脚分析
1.如何确定GPIOE_OSPEEDR寄存器的地址?
    地址=基地址+偏移地址=0x50006000+0x08=0x50006008 
2.通过GPIOE_OSPEEDR设置PE10引脚设置为低速输出模式?
     GPIOE_OSPEEDR[21:20] = 00 ----->设置为低速输出模式
     向0x50006008地址中的第[21:20]写入00

4) 分析GPIOx_PUPDR寄存器

LED1------>PE10引脚分析
1.如何确定GPIOE_PUPDR寄存器的地址?
    地址=基地址+偏移地址=0x50006000+0x0C=0x5000600C
2.通过GPIOE_PUPDR设置PE10引脚设置为禁止上下拉?
     GPIOE_PUPDR[21:20] = 00 ----->设置为禁止上下拉
     向0x5000600C地址中的第[21:20]写入00

 5) 分析GPIOx_ODR寄存器

LED1------>PE10引脚分析
1.如何确定GPIOE_ODR寄存器的地址?
    地址=基地址+偏移地址=0x50006000+0x14=0x50006014
2.通过GPIOE_ODR设置PE10引脚输出高低电平?
     GPIOE_ODR[10] = 0 ----->设置PE10引脚输出低电平
     GPIOE_ODR[10] = 1 ----->设置PE10引脚输出高电平
     向0x50006014地址中的第[10]写入0,输出低电平
     向0x50006014地址中的第[10]写入1,输出高电平

CORTEX A7核实现

汇编代码:

.global _start
_start: 

/**********LED1点亮**************/
LED1_INIT:
	@1.通过RCC_AHB4_ENSETR:0x50000A28寄存器设置GPIOE控制器使能 0x50000A28[4] = 1
	ldr r0,=0x50000A28
	ldr r1,[r0] @将r0寄存器地址中的值,读到r1寄存器中
	orr r1,r1,#(0x1 << 4) 
	@将r1寄存器中的第4位置1
	str r1,[r0]

	@2.通过GPIOE_MODER:0x50006000寄存器设置PE10引脚为输出模式 0x50006000[21:20]= 01
	ldr r0,=0x50006000
	ldr r1,[r0]
	and r1,r1,#(~(0x3 << 20))
	orr r1,r1,#(0x1 << 20)
	str r1,[r0]

	@3.通过GPIOE_OTYPER:0x50006004寄存器设置PE10引脚为推挽输出模式 0x50006004[10]= 0
	ldr r0,=0x50006004
	ldr r1,[r0]
	and r1,r1,#(~(0x1 << 10))
	str r1,[r0]

	@4.通过GPIOE_OSPEEDR:0x50006008寄存器设置PE10引脚为低速输出模式0x50006008[21:20]= 00
	ldr r0,=0x50006008
	ldr r1,[r0]
	and r1,r1,#(~(0x3 << 20))
	str r1,[r0]

	@5.通过GPIOE_PUPDR:0x5000600C寄存器设置PE10引脚为禁止上下拉0x5000600C[21:20]= 00
	ldr r0,=0x5000600C
	ldr r1,[r0]
	and r1,r1,#(~(0x3 << 20))
	str r1,[r0]

/**********LED2点亮PF10**************/
LED2_INIT:
	@1.通过RCC_AHB4_ENSETR:0x50000A28寄存器设置GPIOF控制器使能 0x50000A28[5] = 1
	ldr r0,=0x50000A28
	ldr r1,[r0] @将r0寄存器地址中的值,读到r1寄存器中
	orr r1,r1,#(0x1 << 5) 
	@将r1寄存器中的第4位置1
	str r1,[r0]

	@2.通过GPIOF_MODER:0x50006000寄存器设置PF10引脚为输出模式 0x50007000[21:20]= 01
	ldr r0,=0x50007000
	ldr r1,[r0]
	and r1,r1,#(~(0x3 << 20))
	orr r1,r1,#(0x1 << 20)
	str r1,[r0]

	@3.通过GPIOF_OTYPER:0x50006004寄存器设置PF10引脚为推挽输出模式 0x50007004[10]= 0
	ldr r0,=0x50007004
	ldr r1,[r0]
	and r1,r1,#(~(0x1 << 10))
	str r1,[r0]

	@4.通过GPIOF_OSPEEDR:0x50006008寄存器设置PE10引脚为低速输出模式0x50007008[21:20]= 00
	ldr r0,=0x50007008
	ldr r1,[r0]
	and r1,r1,#(~(0x3 << 20))
	str r1,[r0]

	@5.通过GPIOF_PUPDR:0x5000700C寄存器设置PE10引脚为禁止上下拉0x5000700C[21:20]= 00
	ldr r0,=0x5000700C
	ldr r1,[r0]
	and r1,r1,#(~(0x3 << 20))
	str r1,[r0]

/**********LED3点亮PE8**************/
LED3_INIT:
	@1.通过RCC_AHB4_ENSETR:0x50000A28寄存器设置GPIOE控制器使能 0x50000A28[4] = 1
	ldr r0,=0x50000A28
	ldr r1,[r0] @将r0寄存器地址中的值,读到r1寄存器中
	orr r1,r1,#(0x1 << 4) 
	@将r1寄存器中的第4位置1
	str r1,[r0]

	@2.通过GPIOE_MODER:0x50006000寄存器设置PE8引脚为输出模式 0x50006000[17:16]= 01
	ldr r0,=0x50006000
	ldr r1,[r0]
	and r1,r1,#(~(0x3 << 16))
	orr r1,r1,#(0x1 << 16)
	str r1,[r0]

	@3.通过GPIOE_OTYPER:0x50006004寄存器设置PE8引脚为推挽输出模式 0x50006004[8]= 0
	ldr r0,=0x50006004
	ldr r1,[r0]
	and r1,r1,#(~(0x1 << 8))
	str r1,[r0]

	@4.通过GPIOE_OSPEEDR:0x50006008寄存器设置PE8引脚为低速输出模式0x50006008[17:16]= 00
	ldr r0,=0x50006008
	ldr r1,[r0]
	and r1,r1,#(~(0x3 << 16))
	str r1,[r0]

	@5.通过GPIOE_PUPDR:0x5000600C寄存器设置PE8引脚为禁止上下拉0x5000600C[17:16]= 00
	ldr r0,=0x5000600C
	ldr r1,[r0]
	and r1,r1,#(~(0x3 << 16))
	str r1,[r0]

loop:
	bl LED1_ON
	bl delay_1s
	bl LED1_OFF
	bl delay_1s

	bl LED2_ON
	bl delay_1s
	bl LED2_OFF
	bl delay_1s

	bl LED3_ON
	bl delay_1s
	bl LED3_OFF
	bl delay_1s
	b loop

LED1_ON:
	@1.通过GPIOE_ODR:0x50006014寄存器设置PE10引脚为输出高电平 0x50006014[10]= 1
	ldr r0,=0x50006014
	ldr r1,[r0]
	orr r1,r1,#(0x1 << 10)
	str r1,[r0]
	mov pc,lr

LED2_ON:
	@1.通过GPIOF_ODR:0x50007014寄存器设置PF10引脚为输出高电平 0x50007014[10]= 1
	ldr r0,=0x50007014
	ldr r1,[r0]
	orr r1,r1,#(0x1 << 10)
	str r1,[r0]
	mov pc,lr
LED3_ON:
	@1.通过GPIOE_ODR:0x50006014寄存器设置PE8引脚为输出高电平 0x50006014[8]= 1
	ldr r0,=0x50006014
	ldr r1,[r0]
	orr r1,r1,#(0x1 << 8)
	str r1,[r0]
	mov pc,lr

LED1_OFF:
	@1.通过GPIOE_ODR:0x50006014寄存器设置PE10引脚为输出低电平 0x50006014[10]= 0
	ldr r0,=0x50006014
	ldr r1,[r0]
	and r1,r1,#(~(0x1 << 10))
	str r1,[r0]
	mov pc,lr
LED2_OFF:
	@1.通过GPIOE_ODR:0x50007014寄存器设置PE10引脚为输出低电平 0x50007014[10]= 0
	ldr r0,=0x50007014
	ldr r1,[r0]
	and r1,r1,#(~(0x1 << 10))
	str r1,[r0]
	mov pc,lr

LED3_OFF:
	@1.通过GPIOE_ODR:0x50006014寄存器设置PE10引脚为输出低电平 0x50006014[8]= 0
	ldr r0,=0x50006014
	ldr r1,[r0]
	and r1,r1,#(~(0x1 << 8))
	str r1,[r0]
	mov pc,lr

@ 大概1s的延时函数
delay_1s:
	mov r3, #0x10000000
	mm:
	cmp r3, #0
	subne r3, r3, #1
	bne mm
	mov pc, lr

.end

C语言实现:

头文件编写:

#ifndef __GPIO_H__
#define __GPIO_H__

//1.RCC寄存器封装,用宏定义进行封装
#define RCC_AHB4_ENSETR (*(unsigned int *)0x50000A28)
//2.GPIO寄存器进行封装,用结构体封装
typedef struct{
	volatile unsigned int MODER; //00
	volatile unsigned int OTYPER; //04
	volatile unsigned int OSPEEDR; //08
	volatile unsigned int PUPDR; //0C
	volatile unsigned int IDR; //10
	volatile unsigned int ODR; //14
}gpio_t;
#define GPIOE ((gpio_t*)0x50006000)
#define GPIOF ((gpio_t*)0x50007000)

//引脚封装
#define GPIO_PIN_0 0
#define GPIO_PIN_1 1
#define GPIO_PIN_2 2
#define GPIO_PIN_3 3
#define GPIO_PIN_4 4
#define GPIO_PIN_5 5
#define GPIO_PIN_6 6
#define GPIO_PIN_7 7
#define GPIO_PIN_8 8
#define GPIO_PIN_9 9
#define GPIO_PIN_10 10
#define GPIO_PIN_11 11
#define GPIO_PIN_12 12
#define GPIO_PIN_13 13
#define GPIO_PIN_14 14
#define GPIO_PIN_15 15

//封装模式寄存器
typedef enum{
	INPUT,
	OUTPUT,
	ALT,
	ANALOG,
}gpio_mode_t;

//封装输出类型寄存器
typedef enum{
	PP,
	OD,
}gpio_otyper_t;

//封装输出速度寄存器
typedef enum{
	LOW,
	MED,
	HIGH,
	VERY_HIGH,
}gpio_ospeedr_t;

//封装是否需要上下拉电阻
typedef enum{
	NO_PUPD,
	PU,
	PD,
}gpio_pupdr_t;

//封装输出高低电平
typedef enum{
	GPIO_RESET,
	GPIO_SET,
}gpio_status_t;

//结构体初始化
typedef struct{
	gpio_mode_t moder;
	gpio_otyper_t otyper;
	gpio_ospeedr_t speedr;
	gpio_pupdr_t pupdr;
}gpio_init_t;

//初始化函数
void hal_gpio_init(gpio_t* gpiox,gpio_init_t* init,unsigned int pin);

//写操作函数
void hal_gpio_write(gpio_t* gpiox,unsigned int pin,gpio_status_t state);

#endif

函数封装:

#include "gpio.h"
//初始化函数
void hal_gpio_init(gpio_t* gpiox,gpio_init_t* init,unsigned int pin)
{
	//1.设置输出模式
	gpiox->MODER &= (~(0x3 << (pin * 2)));
	gpiox->MODER |= (init->moder << (pin *2));

	//2.设置输出类型
	gpiox->OTYPER &= (~(0x1 << pin));
	gpiox->OTYPER |= (init->otyper << pin);

	//3.设置输出速度
	gpiox->OSPEEDR &= (~(0x3 << (pin *2)));
	gpiox->OSPEEDR |= (init->speedr << (pin * 2));

	//4.设置是否需要上下拉
	gpiox->PUPDR &= (~(0x3 << (pin * 2)));
	gpiox->PUPDR |= (init->pupdr << (pin * 2));
}

//写操作函数
void hal_gpio_write(gpio_t* gpiox,unsigned int pin,gpio_status_t state)
{
	if(state == GPIO_RESET)
	{
		gpiox->ODR &= (~(0x1 << pin));
	}
	else
	{
		gpiox->ODR |=(0x1 << pin);
	}
}

主函数:

#include "gpio.h"

extern void printf(const char *fmt, ...);
void delay_ms(int ms)
{
	int i,j;
	for(i = 0; i < ms;i++)
		for (j = 0; j < 1800; j++);
}

void led_init()
{
	//1.时钟使能
	RCC_AHB4_ENSETR |= (0x3 << 4);
	//2.led灯结构体初始化
	gpio_init_t init = {OUTPUT,PP,LOW,NO_PUPD};

	hal_gpio_init(GPIOE,&init,GPIO_PIN_10);
	hal_gpio_init(GPIOF,&init,GPIO_PIN_10);
	hal_gpio_init(GPIOE,&init,GPIO_PIN_8);
}

int main()
{
	led_init();
	while(1)
	{
		hal_gpio_write(GPIOE,GPIO_PIN_10,GPIO_SET);
		delay_ms(500);
		hal_gpio_write(GPIOE,GPIO_PIN_10,GPIO_RESET);
		delay_ms(500);

		hal_gpio_write(GPIOF,GPIO_PIN_10,GPIO_SET);
		delay_ms(500);
		hal_gpio_write(GPIOF,GPIO_PIN_10,GPIO_RESET);
		delay_ms(500);

		hal_gpio_write(GPIOE,GPIO_PIN_8,GPIO_SET);
		delay_ms(500);
		hal_gpio_write(GPIOE,GPIO_PIN_8,GPIO_RESET);
		delay_ms(500);
	}
	return 0;
}

 CORTEX M4核实现

一、CubMX工程创建:

 二、配置LED灯

1.配置PE10/PF10/PE8,鼠标左键,设置位输出模式

2.鼠标右键,配置为M4核

 

 

 三、查看配置信息

四、导出工程 

 

 

 五、代码编写

 

KEIL配置:

 

 

 

 

代码块: 

相关文章:

  • 【云原生之Docker实战】使用Docker部署Lsky Pro个人图床平台
  • 【剑指Offer】--->详解二分查找相关练习
  • 如何使用SpringBoot里面的StopWatch统计耗时
  • 图解网络 记录
  • 嵌入式AI入坑经历
  • 【QT学习】如何自定义exe图标和详细信息?(三分钟解决)
  • 【CSS3】 平面转换 空间转换 动画
  • 北斗导航 | Visual Studio 2015之RTKLib Demo5配置
  • 哈工大李治军老师操作系统笔记【29】:目录与文件系统(Learning OS Concepts By Coding Them !)
  • 网络安全基础
  • C++ stackqueue 栈和队列的使用模拟实现
  • Hadoop之企业级解决方案
  • 【C语言】default 关键字
  • python小游戏源码
  • 【C++11新增知识点】右值引用、移动语义、完美转发
  • AHK 中 = 和 == 等比较运算符的用法
  • C++11: atomic 头文件
  • co.js - 让异步代码同步化
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • Django 博客开发教程 8 - 博客文章详情页
  • ECMAScript6(0):ES6简明参考手册
  • es的写入过程
  • express.js的介绍及使用
  • Nodejs和JavaWeb协助开发
  • React中的“虫洞”——Context
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • webpack4 一点通
  • 来,膜拜下android roadmap,强大的执行力
  • 两列自适应布局方案整理
  • 微信小程序实战练习(仿五洲到家微信版)
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • (30)数组元素和与数字和的绝对差
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (Redis使用系列) Springboot 使用redis的List数据结构实现简单的排队功能场景 九
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (附源码)计算机毕业设计高校学生选课系统
  • (一)WLAN定义和基本架构转
  • (转)Oracle 9i 数据库设计指引全集(1)
  • (转)为C# Windows服务添加安装程序
  • (状压dp)uva 10817 Headmaster's Headache
  • .net操作Excel出错解决
  • .NET设计模式(7):创建型模式专题总结(Creational Pattern)
  • .NET中GET与SET的用法
  • /dev下添加设备节点的方法步骤(通过device_create)
  • :not(:first-child)和:not(:last-child)的用法
  • @SentinelResource详解
  • @WebServiceClient注解,wsdlLocation 可配置
  • [Android]RecyclerView添加HeaderView出现宽度问题
  • [BUUCTF NewStarCTF 2023 公开赛道] week4 crypto/pwn
  • [ERROR] Plugin 'InnoDB' init function returned error
  • [E链表] lc83. 删除排序链表中的重复元素(单链表+模拟)
  • [iOS]-网络请求总结
  • [JS]JavaScript 简介
  • [mvc] 简单的forms认证