欢迎回到我们的RA系列FSP库开发实战指南频道,下面我们将继续讲解“自己写库——构建库函数雏形”部分:
8.2.5定义IO初始化结构体
由上述IOPORT相关功能的枚举类型我们可以知道,在对IOPORT模块进行初始化时需要根据情况配置它们。因此我们定义一个IOPORT初始化的结构体类型IOPORT_Init_t,它的成员包括了由上述所有枚举类型所声明的变量,因此该结构体类型的变量可以包含IOPORT的相关功能配置。
列表5:代码清单8-4:ra_ioport.h文件
左右滑动查看完整内容
/* IOPORT 初始化结构体类型定义 */
typedefstruct
{
IO_Port_tPort;
IO_Pin_tPin;
IO_Mode_tMode;
IO_Dir_tDir;
IO_OType_tOType;
IO_DriveCapability_tDrive;
IO_Level_tLevel;
IO_Pull_tPull;
} IOPORT_Init_t;
8.2.6编写IO操作函数
我们把IO操作函数的声明和IO初始化函数的声明都放在ra_ioport.h头文件。
列表6:代码清单8-5:ra_ioport.h文件
左右滑动查看完整内容
/* IO 操作函数(调用一次只能操作一个 IO 引脚) */ uint32_tIOPORT_PinRead(IO_Port_t port, IO_Pin_t pin); voidIOPORT_PinWrite(IO_Port_t port, IO_Pin_t pin, IO_Level_t␣ →level); voidIOPORT_PinToggle(IO_Port_t port, IO_Pin_t pin); voidIOPORT_PinAccessEnable(void); voidIOPORT_PinAccessDisable(void); /* IO 初始化函数(调用一次只能初始化一个 IO 引脚) */ voidIOPORT_Init(IOPORT_Init_t *ioport_init);
然后在ra_ioport.c源文件里面实现这些IO操作函数。
列表7:代码清单8-6:ra6m5_ioport.c文件
左右滑动查看完整内容
/* 读引脚电平 */
uint32_tIOPORT_PinRead(IO_Port_t port, IO_Pin_t pin)
{
/* Read pin level. */
returnR_PFS->PORT[port >>8].PIN[pin].PmnPFS_b.PIDR;
}
/* 写引脚电平 */
voidIOPORT_PinWrite(IO_Port_t port, IO_Pin_t pin, IO_Level_t level)
{
uint32_t pfs_bits =R_PFS->PORT[port >>8].PIN[pin].PmnPFS;//读寄存器␣
→PmnPFS
pfs_bits &= ~(uint32_t)0x1;//清零 PODR 位
R_PFS->PORT[port >>8].PIN[pin].PmnPFS= (pfs_bits | level);
}
/* 翻转引脚电平 */
voidIOPORT_PinToggle(IO_Port_t port, IO_Pin_t pin)
{
uint32_t pfs_bits =R_PFS->PORT[port >>8].PIN[pin].PmnPFS;//读寄存器␣
→PmnPFS
pfs_bits ^= (uint32_t)0x1;//取反 PODR 位
R_PFS->PORT[port >>8].PIN[pin].PmnPFS= pfs_bits;
}
/* 引脚访问使能 */
voidIOPORT_PinAccessEnable(void)
{
R_PMISC->PWPR=0;///< Clear BOWI bit - writing to PFSWE bit␣
→enabled
R_PMISC->PWPR= 1U << 6U; ///< Set PFSWE bit - writing to PFS register␣
→enabled
}
/* 引脚访问禁止 */
voidIOPORT_PinAccessDisable(void)
{
R_PMISC->PWPR=0;///< Clear PFSWE bit - writing to PFS register␣
→disabled
R_PMISC->PWPR= 1U << 7U; ///< Set BOWI bit - writing to PFSWE bit␣
→disabled
}
8.2.7编写IO初始化函数
最后编写IOPORT初始化函数。
列表8:代码清单8-7:ra_ioport.c文件
左右滑动查看完整内容
/* IOPORT 初始化函数 */
voidIOPORT_Init(IOPORT_Init_t *ioport_init)
{
uint32_t pfs_bits =0;//不读取寄存器 PmnPFS
if(ioport_init->Mode==IO_MODE_GPIO)//如果引脚用作普通 GPIO 功能
{
if(ioport_init->Dir==IO_DIR_INPUT)/* 用作输入模式 */
{
pfs_bits |= (ioport_init->Pull) << 4; //设置输入上拉
}
elseif(ioport_init->Dir==IO_DIR_OUTPUT)/* 用作输出模式 */
{
pfs_bits |= (ioport_init->Dir) << 2; //设置为输出
pfs_bits |= (ioport_init->Level) << 0; //设置输出电平
pfs_bits |= (ioport_init->Mode) << 6; //设置输出模式
pfs_bits |= (ioport_init->Drive) << 10; //设置输出驱动能力
}
}
else
{
//我们不考虑引脚用作复用模式和模拟输入输出模式的情况
//也不考虑中断的情况,仅考虑普通的 GPIO 输入输出功能
}
/* 写入配置到寄存器 PmnPFS */
R_PFS->PORT[ioport_init->Port>>8].PIN[ioport_init->Pin].PmnPFS= pfs_
→bits;
}
8.2.8hal_entry入口函数
前一章节实验里有讲过,当使用RTOS时,程序从main函数开始进行线程调度;当没有使用RTOS时,C语言程序的入口函数main函数调用了hal_entry函数。本章节实验的工程也是没有选用RTOS的,因此,用户程序是从hal_entry函数开始执行。
打开“srchal_entry.c”文件,我们在“hal_entry.c”文件中添加对头文件“ra_ioport.h”的包含,然后在hal_entry函数里面编写我们的代码。
以启明6M5开发板为例,RA6M5工程的hal_entry数代码如下所示。
注解
启明4M2开发板和启明2L1开发板的用户可直接打开配套的“09_Register_MyLib”例程查看该代码,限于篇幅,不在本章中贴出。
列表9:代码清单8-8:hal_entry.c文件
左右滑动查看完整内容
/* IOPORT 模块头文件 (自己写库——构建库函数雏形) */
#include"ioport/ra_ioport.h"
voidhal_entry(void)
{
/*TODO:add your own code here */
/* 调用取消写保护函数 */
IOPORT_PinAccessEnable();
/* 使用 IOPORT 初始化结构体和调用初始化函数来配置 PFS 寄存器 */
IOPORT_Init_t led_io_init;
led_io_init.Port = IO_PORT_04;
led_io_init.Pin = IO_PIN_00;
led_io_init.Mode = IO_MODE_GPIO;//普通 GPIO 模式,而不是复用功能模式或其他
的
led_io_init.Dir = IO_DIR_OUTPUT;
led_io_init.OType = IO_OTYPE_PP;
led_io_init.Drive = IO_DRIVE_LOW;
led_io_init.Level = IO_LEVEL_HIGH;//输出高电平(LED 熄灭)
//LED_IO_Init.Pull = IO_NO_PULL; //端口方向处于输出模式下是用不了上拉的,所以这
个属性没意义
IOPORT_Init(&led_io_init);//调用初始化函数,进行 LED1 引脚初始化
led_io_init.Pin = IO_PIN_03;//更换引脚号
IOPORT_Init(&led_io_init);//结构体其他属性不变,再次调用初始化函数,进行 LED2 引
脚初始化
led_io_init.Pin = IO_PIN_04;//更换引脚号
IOPORT_Init(&led_io_init);//结构体其他属性不变,再次调用初始化函数,进行 LED3 引
脚初始化
/** 此时 3 个 LED 灯的引脚默认输出的是高电平,所以 3 个 LED 灯都会默认不亮
* 我们先打开所有 LED 灯,然后在 while 循环里让 LED1 闪烁:每秒钟翻转一次状态
*/
IOPORT_PinWrite(IO_PORT_04, IO_PIN_00, IO_LEVEL_LOW);//点亮 LED1
IOPORT_PinWrite(IO_PORT_04, IO_PIN_03, IO_LEVEL_LOW);//点亮 LED2
IOPORT_PinWrite(IO_PORT_04, IO_PIN_04, IO_LEVEL_LOW);//点亮 LED3
while(1)
{
/* 使用函数 IOPORT_PinToggle 翻转 LED1 引脚电平 */
IOPORT_PinToggle(IO_PORT_04, IO_PIN_00);
R_BSP_SoftwareDelay(1000, BSP_DELAY_UNITS_MILLISECONDS);
}
#ifBSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
8.3下载验证
编写好上述代码,然后将程序编译并下载到开发板之后,按下复位按键来复位开发板,可以观察到实验现象与上一章的实验现象相同:开发板上面除了电源指示灯之外的3个LED灯当中有两个灯常亮,还有一个灯在缓慢闪烁。闪烁着的LED灯为LED1,它每秒钟(1000毫秒)便改变一次亮灭的状态。
-
函数
+关注
关注
3文章
4406浏览量
66858 -
开发板
+关注
关注
25文章
6139浏览量
113563 -
结构体
+关注
关注
1文章
131浏览量
11300 -
FSP
+关注
关注
0文章
47浏览量
7656
发布评论请先 登录
RT-Thread自动初始化详解
LED实验中把结构体定义放在时钟初始化后出现报错
定时器初始化结构体定义
【原创分享】变量的初始化技巧
STM32f1单片机的HAL库是如何去定义定时器相关的初始化结构体的
利用结构体数组方便地控制单片机IO相关资料推荐
结构体数组的初始化
结构体的定义、初始化和赋值
STM32的IO口基本操作:初始化结构体,设置系统时钟,开启外设时钟资料下载
GraniStudio:IO初始化以及IO资源配置例程

定义IO初始化结构体
评论