云计算百科
云计算领域专业知识百科平台

蓝牙遥控的电子小狗!【1.2 基于瑞萨RA4M2单片机设计的保姆级教程】

        在本篇文章中,作者将从零开始带领大家利用瑞萨RA4M2系列单片机设计一款属于自己的蓝牙遥控小狗。什么?连创建工程都不会!没关系,作者带着你从创建工程开始,急速通关!

一、硬件准备

1.瑞萨RA4M2系列单片机

2.一块面包板或者以及画好的PCB板(作者会附上自己的PCB制板文件与工程文件)

3.杜邦线若干

4.可输出3.3v和5v的电源模块,3.3v为单片机和舵机供电,5v为蓝牙模块供电

5.5个可由3.3v电压驱动的SG90舵机模块

6.DX-BT24蓝牙模块(低功耗蓝牙透传模块)

二、软件准备

        在正式开始之前,大家需要准备好最基础的两个软件

        (1)e2 studio:这是瑞萨电子(Renesas Electronics)推出的一款集成开发环境(IDE),专门用于瑞萨微控制器(MCU)的嵌入式软件开发。我们需要用它来进行程序的编写。

        (2)Renesas Flash Programmer :这是瑞萨电子官方提供的一款独立的闪存编程工具,专门用于对瑞萨微控制器(MCU)的内置闪存进行编程(烧录)和擦除。我们需要用它来进行程序的烧录。

三、工程创建

1.选取工作空间

        我们双击打开 e2 studio,会跳出一个弹窗要求我们选取工作空间,第一次使用e2 studio的同学们可以先在C盘或者D盘中创建一个文件夹,起名为e2s_workspace作为工作空间,也就是后续开发中我们工程文件存放的地方,创建完成后,我们回到此页面点击浏览,选择自己刚刚创建的文件夹作为工作空间,随后我们点击启动。

2.创建新工程

2.1新建项目

        进入e2 studio后,我们点击左上角的文件,选择新建,接着选择瑞萨C/C++项目,最后点击Renesas RA

 2.2选取工程模板

        进入项目模板窗口后我们选择第一个作为项目模板,点击下一步

2.3确定项目名称

        接下来为我们的项目起一个自己喜欢的名字,比如作者起的项目名就是Dog,起完名后点击下一步

2.4设备与工具选择

        接下来的配置至关重要:

        (1)确认FSP版本:作者使用的版本为5.9.0,不同版本之间,函数的使用可能存在一些差异。

        (2)选取单片机型号:在Device一栏中选取我们的单片机型号,作者选用的是 R7FA4M2AD3CFL

        (3)调试器选取:使用USB-typec线向单片机中烧录程序的同学将调试器配置为J-Llink ARM

        (4)工具链选取:选择第二个GNU ARM Embedded 工具链,这是一套由 ARM 官方维护和支持的、用于开发 ARM Cortex-M 和 Cortex-R 系列微控制器的免费、开源编译工具集合。

        (5)点击下一步       

2.5其他配置

        在完成上一步配置之后,接下来弹出的配置页面我们全部保持默认选项,一直点击下一步,直到出现完成,点击完成。这样我们就成功创建了一个新工程!此时我们进入了图形化配置界面。

四、图形化配置

1.打开图形化配置

        一般来说在创建完工程后系统会直接打开图形化配置界面,但当我们误关闭图形化配置时,我们可以在左侧的项目资源管理器中重新找到并打开它。

2.时钟树配置

        在图形化配置最下方的菜单栏中选择Clocks打开时钟树,如图进行配置,将时钟主频控制在合适的范围内,有stm32基础的同学可以按自己的需求修改。        

3.调试引脚配置

        在单片机中Pin就是引脚的意思,我们点击最下方菜单栏中的Pins打开引脚配置界面。在左侧选择系统调试选项,然后将调试模式改为SWD(Serial Wire Debug),再将引脚如图分别配置为P300和P108。如果自处默认配置为SWD的同学则可以不改。

4.定时器配置

        在本项目中需要用PWM波来驱动舵机旋转,所以我们需要将定时器配置为PWM波生成模式,其实PWM波就是由单片机产生的固定频率和占空比的方波,想要了解PWM和舵机驱动方式的同学可以去看作者另外一篇关于智能垃圾桶设计的文章,里面做了详细的介绍,接下来我们开始配置:

4.1创建组件

        点击最下方菜单栏里的Stacks进入软件组件与驱动模块配置,进入该界面后点击右上角的

New Stacks选项,在其中选择Timers,随后选择PWM生成模式。

4.2属性配置

        创建完成后我们选中刚刚创建的组件,进行属性配置。

(1)修改定时器的名字,这里可以根据自己的需求进行修改,根本目的是为了提高后续代码的可读性,要不然到时候写着写着都不知道自己这个定时器是干啥的了,比如作者将要使用这个定时器生成PWM来驱动电子小狗的右前腿,就可以把名字改成R_Front_Foot

(2)选取定时器通道,不同型号的单片机自带的定时器通道可能有所差异,具体有哪些定时器通道,感兴趣的可以去查阅手册,不确定的就按照作者的配置方法进行配置

(3)将Mode设为 Periodic,表示该定时器工作在周期模式,将在设定周期内重复运行

(4)将Period设置为50,并把Period Unit设置为50HZ,因为SG90舵机只能使用频率为50hz的PWM波进行驱动,具体为什么可以看作者之前智能垃圾桶那篇文章,里面有提及

(5)初始时将Duty Cycle Percent设置为 50%,表示 PWM 输出信号的高电平时间占周期50%,但是我们后面控制舵机时会改变占空比,这里可以设置成别的数

(6)将GTIOCA Output Enabled设置为 True,启用 GTIOCA引脚的输出功能,这样我们的PWM信号才能通过引脚向外输出

(7)将GTIOCA Stop Level设为 Pin Level Low,表示定时器停止时 GTIOCA 输出低电平。

(8)最后我们选择合适的输出引脚,这里作者选择的是P407

 4.3其他定时器配置

        配置完右前腿后我们再进行另外四个定时器的配置,分别控制剩下来4个舵机,如法炮制,流程都是一样的,这里就不再赘述,直接放上配置图片~

5.串口配置

5.1创建组件

        像定时器配置一样,我们首先创建组件,如图按步骤进行配置,照样先点击New Stacks,随后选择Connectivity,最后选择UART(r_sci_uart)

5.2属性配置

        点击我们刚刚创建的串口组件,我们进行属性配置

(1)由于我们创建的串口组件将用于和蓝牙模块通信,所以我们不妨将它的名字改为Blue_Tooth

(2)选择合适的串口通道,如果选择了错误的串口通道会报错

(3)由于作者选用的蓝牙模块是BT24,所以数据位,校验位和停止位都保持默认,如果你选用的是其他蓝牙模块需要根据所选蓝牙模块的参数进行修改

(4)设置波特率,BT24蓝牙模块需要的波特率是9600,只有当波特率相同时,单片机才能和蓝牙模块实现通信

(5)打开波特率调制模式,单片机可以根据实际情况自适应的调制波特率

(6)开启串口的中断回调模式,初始时Callback这一行会显示NULL表示未开启,我们给它命名后则默认开始,此处最好后缀加上callback,在后续代码编写中我们可以轻松的分辨出这是中断回调函数。中断回调顾名思义,当满足特殊条件时将会打断主程序而去执行该函数中的内容,比如当串口信号接收完成时会触发中断,在Callback下方有列举触发中断的事件

(7)中断事件的优先级可以保持默认,因为我们的程序不是很复杂,当前只有这一个中断

(8)选取合适的引脚进行配置,TX是单片机发出信号的引脚,RX是单片机接收信号的引脚,那么到时候单片机的TX就得和蓝牙模块的RX进行连接,而单片机的RX则得和蓝牙模块的TX进行连接。
 

6.Generate Project Content

        在完成所有的图形化配置后一定要点击右上角的Generate Project Content它的核心作用是将你在 FSP 配置视图中进行的所有图形化设置,转换为实际的项目源代码和配置文件。

五、代码编写

1.PWM驱动编写

        (1)在这部分中我们会用到许多与定时器相关的函数,但由于我们这是速成教程,同学们只需要学会怎么移植就行了。所有带_ctrl和_cfg后缀的都是系统已经创建好的结构体,我们只需要将它们前面的部分换成自己创建的定时器的名字,自定义函数的名称也可以根据自己的喜好进行修改。

        (2)接下来我们需要将作者提供的代码搬运到自己的工程中,我们在左侧的项目资源管理器中找到src文件夹,右键,选择新建,选择新建源文件,记住为新建源文件命名时一定要加上.c后缀

        (3)创建完成后将下面这段代码复制到源文件中,报错内容先不要管

#include "pwm.h"

//右前腿初始化
void R_Front_Init(void)
{
/* 初始化 GPT 模块 */
R_GPT_Open(&R_Front_Foot_ctrl, &R_Front_Foot_cfg);
/* 启动 GPT 定时器 */
R_GPT_Start(&R_Front_Foot_ctrl);
}

//左前腿初始化
void L_Front_Init(void)
{
/* 初始化 GPT 模块 */
R_GPT_Open(&L_Front_Foot_ctrl, &L_Front_Foot_cfg);
/* 启动 GPT 定时器 */
R_GPT_Start(&L_Front_Foot_ctrl);
}
//右后腿初始化
void R_Rear_Init(void)
{
/* 初始化 GPT 模块 */
R_GPT_Open(&R_Rear_Foot_ctrl, &R_Rear_Foot_cfg);
/* 启动 GPT 定时器 */
R_GPT_Start(&R_Rear_Foot_ctrl);
}
//左后腿初始化
void L_Rear_Init(void)
{
/* 初始化 GPT 模块 */
R_GPT_Open(&L_Rear_Foot_ctrl, &L_Rear_Foot_cfg);
/* 启动 GPT 定时器 */
R_GPT_Start(&L_Rear_Foot_ctrl);
}
//尾巴初始化
void Tail_Init(void)
{
/* 初始化 GPT 模块 */
R_GPT_Open(&Tail_ctrl, &Tail_cfg);
/* 启动 GPT 定时器 */
R_GPT_Start(&Tail_ctrl);
}

//设置右前腿的占空比
void R_Front_SetDuty(uint8_t duty)
{
timer_info_t info1;
uint32_t current_period_counts1;
uint32_t duty_cycle_counts1;

if (duty > 100)
duty = 100; //限制占空比范围:0~100

/* 获得GPT的信息 */
R_GPT_InfoGet(&R_Front_Foot_ctrl, &info1);

/* 获得计时器一个周期需要的计数次数 */
current_period_counts1 = info1.period_counts;

/* 根据占空比和一个周期的计数次数计算GTCCR寄存器的值 */
duty_cycle_counts1 = (uint32_t)(((uint64_t) current_period_counts1 *(100 – duty)) / 100);

/* 最后调用FSP库函数设置占空比 */
R_GPT_DutyCycleSet(&R_Front_Foot_ctrl, duty_cycle_counts1, GPT_IO_PIN_GTIOCA);
}

//设置左前腿的占空比
void L_Front_SetDuty(uint8_t duty)
{
timer_info_t info;
uint32_t current_period_counts;
uint32_t duty_cycle_counts;

if (duty > 100)
duty = 100; //限制占空比范围:0~100

/* 获得GPT的信息 */
R_GPT_InfoGet(&L_Front_Foot_ctrl, &info);

/* 获得计时器一个周期需要的计数次数 */
current_period_counts = info.period_counts;

/* 根据占空比和一个周期的计数次数计算GTCCR寄存器的值 */
duty_cycle_counts = (uint32_t)(((uint64_t) current_period_counts *(100 – duty)) / 100);

/* 最后调用FSP库函数设置占空比 */
R_GPT_DutyCycleSet(&L_Front_Foot_ctrl, duty_cycle_counts, GPT_IO_PIN_GTIOCA);
}

//设置左后腿的占空比
void L_Rear_SetDuty(uint8_t duty)
{
timer_info_t info;
uint32_t current_period_counts;
uint32_t duty_cycle_counts;

if (duty > 100)
duty = 100; //限制占空比范围:0~100

/* 获得GPT的信息 */
R_GPT_InfoGet(&L_Rear_Foot_ctrl, &info);

/* 获得计时器一个周期需要的计数次数 */
current_period_counts = info.period_counts;

/* 根据占空比和一个周期的计数次数计算GTCCR寄存器的值 */
duty_cycle_counts = (uint32_t)(((uint64_t) current_period_counts *(100 – duty)) / 100);

/* 最后调用FSP库函数设置占空比 */
R_GPT_DutyCycleSet(&L_Rear_Foot_ctrl, duty_cycle_counts, GPT_IO_PIN_GTIOCA);
}
//设置右后腿的占空比
void R_Rear_SetDuty(uint8_t duty)
{
timer_info_t info;
uint32_t current_period_counts;
uint32_t duty_cycle_counts;

if (duty > 100)
duty = 100; //限制占空比范围:0~100

/* 获得GPT的信息 */
R_GPT_InfoGet(&R_Rear_Foot_ctrl, &info);

/* 获得计时器一个周期需要的计数次数 */
current_period_counts = info.period_counts;

/* 根据占空比和一个周期的计数次数计算GTCCR寄存器的值 */
duty_cycle_counts = (uint32_t)(((uint64_t) current_period_counts *(100 – duty)) / 100);

/* 最后调用FSP库函数设置占空比 */
R_GPT_DutyCycleSet(&R_Rear_Foot_ctrl, duty_cycle_counts, GPT_IO_PIN_GTIOCA);
}
//设置尾巴的占空比
void Tail_SetDuty(uint8_t duty)
{
timer_info_t info;
uint32_t current_period_counts;
uint32_t duty_cycle_counts;

if (duty > 100)
duty = 100; //限制占空比范围:0~100

/* 获得GPT的信息 */
R_GPT_InfoGet(&Tail_ctrl, &info);

/* 获得计时器一个周期需要的计数次数 */
current_period_counts = info.period_counts;

/* 根据占空比和一个周期的计数次数计算GTCCR寄存器的值 */
duty_cycle_counts = (uint32_t)(((uint64_t) current_period_counts *(100 – duty)) / 100);

/* 最后调用FSP库函数设置占空比 */
R_GPT_DutyCycleSet(&Tail_ctrl, duty_cycle_counts, GPT_IO_PIN_GTIOCA);
}

        (4)接着我们如法炮制,在src文件夹新建一个源文件,同样在为源文件命名时一定要加上.h后缀,创建完成后将作者关于PWM驱动源文件的代码复制到你所创建的源文件中

#ifndef PWM_PWM_H_
#define PWM_PWM_H_

#include "hal_data.h"
//模块初始化
void R_Front_Init(void);
void L_Front_Init(void);
void R_Rear_Init(void);
void L_Rear_Init(void);
void Tail_Init(void);

//占空比设置
void R_Front_SetDuty(uint8_t duty);
void L_Front_SetDuty(uint8_t duty);
void R_Rear_SetDuty(uint8_t duty);
void L_Rear_SetDuty(uint8_t duty);
void Tail_SetDuty(uint8_t duty);

#endif /* PWM_PWM_H_ */

2.小狗动作函数编写

        (1)控制舵机时只能用频率为50hz,占空比为2.5%到12.5%的PWM波控制,根据作者刚刚在PWM源文件中为大家提供的设置占空比的函数,我们只需要在函数中填入2~13之间的整数,即可控制舵机在0~180度之间旋转。

        (2)由此,我们可以设计出多样化的动作,下面作者同样为大家提供了控制动作的源文件与头文件,当然作者给出的数值是基于作者舵机的摆放位置测算出来的合适数值,如果舵机的安放位置与作者不同,那么你需要自己根据实际情况调整占空比,想要自己设计新的动作也是一个道理。

        (3)下图是作者舵机的摆放方位(第二长图从左往右数第一个舵机是左前腿)

        (4)下面是动作控制的源文件

#include "action.h"
#include "PWM.h"

void stand()//站起来
{
R_Front_SetDuty(7);
L_Front_SetDuty(7);
R_Rear_SetDuty(7);
L_Rear_SetDuty(7);

}
void sleep()//趴下
{
R_Front_SetDuty(3);
L_Front_SetDuty(11);
R_Rear_SetDuty(3);
L_Rear_SetDuty(11);

}

void Forward()//前进
{
for(int i = 0;i<5;i++)
{
R_Front_SetDuty(10);
L_Rear_SetDuty(4);
R_Rear_SetDuty(10);
L_Front_SetDuty(4);
R_BSP_SoftwareDelay(150, BSP_DELAY_UNITS_MILLISECONDS);

R_Front_SetDuty(7);
L_Rear_SetDuty(7);
R_Rear_SetDuty(10);
L_Front_SetDuty(4);
R_BSP_SoftwareDelay(150, BSP_DELAY_UNITS_MILLISECONDS);

R_Front_SetDuty(7);
L_Rear_SetDuty(7);
R_Rear_SetDuty(7);
L_Front_SetDuty(7);
R_BSP_SoftwareDelay(150, BSP_DELAY_UNITS_MILLISECONDS);

R_Front_SetDuty(10);
L_Rear_SetDuty(4);
R_Rear_SetDuty(7);
L_Front_SetDuty(7);
R_BSP_SoftwareDelay(150, BSP_DELAY_UNITS_MILLISECONDS);

}

}

void Turn_Right()
{
L_Front_SetDuty(10);
for(int i = 0;i<5;i++)
{
R_Front_SetDuty(4);
R_Rear_SetDuty(10);
L_Rear_SetDuty(10);
R_BSP_SoftwareDelay(250, BSP_DELAY_UNITS_MILLISECONDS);

R_Front_SetDuty(10);
R_Rear_SetDuty(4);
L_Rear_SetDuty(4);
R_BSP_SoftwareDelay(250, BSP_DELAY_UNITS_MILLISECONDS);
}
}

void Turn_Left()
{
R_Front_SetDuty(10);
for(int i = 0;i<5;i++)
{
L_Front_SetDuty(4);
R_Rear_SetDuty(10);
L_Rear_SetDuty(10);
R_BSP_SoftwareDelay(250, BSP_DELAY_UNITS_MILLISECONDS);

L_Front_SetDuty(10);
R_Rear_SetDuty(4);
L_Rear_SetDuty(4);
R_BSP_SoftwareDelay(250, BSP_DELAY_UNITS_MILLISECONDS);
}
}

void Shake_Tail()
{
R_Front_SetDuty(3);
L_Front_SetDuty(11);
R_Rear_SetDuty(7);
L_Rear_SetDuty(7);
for(int i = 0;i<5;i++)
{
Tail_SetDuty(3);
R_BSP_SoftwareDelay(250, BSP_DELAY_UNITS_MILLISECONDS);
Tail_SetDuty(11);
R_BSP_SoftwareDelay(250, BSP_DELAY_UNITS_MILLISECONDS);
}
}

void Shake_Hand()
{
R_Rear_SetDuty(3);
L_Rear_SetDuty(11);
L_Front_SetDuty(7);
for(int i = 0;i<5;i++)
{
R_Front_SetDuty(12);
R_BSP_SoftwareDelay(250, BSP_DELAY_UNITS_MILLISECONDS);
R_Front_SetDuty(9);
R_BSP_SoftwareDelay(250, BSP_DELAY_UNITS_MILLISECONDS);
}

}

void Gasp()
{
R_Rear_SetDuty(7);
L_Rear_SetDuty(7);
R_Front_SetDuty(7);
L_Front_SetDuty(7);

}

        (5)下面是动作驱动的源文件

#ifndef ACTION_H_
#define ACTION_H_

void stand();
void sleep();//趴下
void Forward();//前进
void Turn_Left();
void Turn_Right();
void Shake_Tail();
void Shake_Hand();
void Gasp();

#endif /* ACTION_H_ */

3.主函数编写

        (1)在左侧项目资源管理器中打开src文件,其中的hal_entry.c就是我们的主函数文件,在开头先引入我们刚刚创建的两个头文件

#include "PWM.h"
#include "action.h"

        (2)首先我们找到 void hal_entry(void) 函数,在其中初始化模块,并且开启串口接收

void hal_entry(void)
{
/* TODO: add your own code here */
R_Front_Init();//初始化右前腿
L_Front_Init();//初始化左前腿
R_Rear_Init();//初始化右后腿
L_Rear_Init();//初始化左后腿
Tail_Init();//初始化尾巴

R_SCI_UART_Open(&Blue_Tooth_ctrl,&Blue_Tooth_cfg);//开启串口
R_SCI_UART_Read(&Blue_Tooth_ctrl,MODE,1);//开启串口接收
}

        (3)由于我们的电子小狗存在多种动作模式,我们将代码放在while(1)死循环中,不断判断当前是否要做动作,再使用一个switch语句来判断当前究竟该执行哪个动作,并在执行完成动作后再次打开串口接收

while (1)
{
if(Flag == 1)
{
Flag = 0;
switch(MODE[0])//行为模式判别
{
case Stand_mode:
stand();
break;
case Sleep_mode:
sleep();
break;
case Forward_mode:
Forward();
break;
case Turn_Left_mode:
Turn_Left();
break;
case Turn_Right_mode:
Turn_Right();
break;
case Tail_mode:
Shake_Tail();
break;
case Shake_Hand_mode:
Shake_Hand();
break;
case Gasp_mode:
Gasp();
break;
default:
break;
}
R_SCI_UART_Read(&Blue_Tooth_ctrl,MODE,1);//开启串口接收
}

R_BSP_SoftwareDelay(20, BSP_DELAY_UNITS_MILLISECONDS);

}

        (4)模式的切换我们放在中断回调函数中,当串口接收完成数据后,会中断主函数进入回调函数,我们在该函数中将是否执行动作的标志位置1,告诉主函数可以开始做动作了

        (5)作者通过手机蓝牙助手发送的信号是字符类型的12345等等数字,他们的本质是Ascll码,并不是真正的数字1234,我们需要经过处理,将他们与字符0相减从而将他们转化为整数类型的1234用于switch中模式的判断

uint8_t MODE[1];
uint8_t Flag = 0;
void Blue_Tooth_Callback(uart_callback_args_t *p_args)
{
if(p_args->event == UART_EVENT_RX_COMPLETE)
{
Flag = 1;
MODE[0] = MODE[0] – '0';
//R_SCI_UART_Write(&Blue_Tooth_ctrl,MODE,1);//开启串口接收
}
}

        (6)为了提升代码的可读性,我们通过宏定义将1234改成更好辨认的方式

//模式定义区
#define Stand_mode 0 //站立
#define Sleep_mode 1 //睡觉
#define Forward_mode 2 //前进
#define Turn_Left_mode 3 //左转
#define Turn_Right_mode 4 //右转
#define Tail_mode 5 //摇尾巴
#define Shake_Hand_mode 6 //握手
#define Gasp_mode 7 //哈气

        (7)下面是主函数中完整的代码展示

#include "hal_data.h"
#include "PWM.h"
#include "action.h"

//模式定义区
#define Stand_mode 0 //站立
#define Sleep_mode 1 //睡觉
#define Forward_mode 2 //前进
#define Turn_Left_mode 3 //左转
#define Turn_Right_mode 4 //右转
#define Tail_mode 5 //摇尾巴
#define Shake_Hand_mode 6 //握手
#define Gasp_mode 7 //哈气

FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER

uint8_t MODE[1];
uint8_t Flag = 0;
void Blue_Tooth_Callback(uart_callback_args_t *p_args)
{
if(p_args->event == UART_EVENT_RX_COMPLETE)
{
Flag = 1;
MODE[0] = MODE[0] – '0';
//R_SCI_UART_Write(&Blue_Tooth_ctrl,MODE,1);//开启串口接收
}
}

/*******************************************************************************************************************//**
* main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used. This function
* is called by main() when no RTOS is used.
**********************************************************************************************************************/
void hal_entry(void)
{
/* TODO: add your own code here */
R_Front_Init();//初始化右前腿
L_Front_Init();//初始化左前腿
R_Rear_Init();//初始化右后腿
L_Rear_Init();//初始化左后腿
Tail_Init();//初始化尾巴

R_SCI_UART_Open(&Blue_Tooth_ctrl,&Blue_Tooth_cfg);//开启串口
R_SCI_UART_Read(&Blue_Tooth_ctrl,MODE,1);//开启串口接收

while (1)
{
if(Flag == 1)
{
Flag = 0;
switch(MODE[0])//行为模式判别
{
case Stand_mode:
stand();
break;
case Sleep_mode:
sleep();
break;
case Forward_mode:
Forward();
break;
case Turn_Left_mode:
Turn_Left();
break;
case Turn_Right_mode:
Turn_Right();
break;
case Tail_mode:
Shake_Tail();
break;
case Shake_Hand_mode:
Shake_Hand();
break;
case Gasp_mode:
Gasp();
break;
default:
break;
}
R_SCI_UART_Read(&Blue_Tooth_ctrl,MODE,1);//开启串口接收
}

R_BSP_SoftwareDelay(20, BSP_DELAY_UNITS_MILLISECONDS);

}

#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}

/*******************************************************************************************************************//**
* This function is called at various points during the startup process. This implementation uses the event that is
* called right before main() to set up the pins.
*
* @param[in] event Where at in the start up process the code is currently at
**********************************************************************************************************************/
void R_BSP_WarmStart(bsp_warm_start_event_t event)
{
if (BSP_WARM_START_RESET == event)
{
#if BSP_FEATURE_FLASH_LP_VERSION != 0

/* Enable reading from data flash. */
R_FACI_LP->DFLCTL = 1U;

/* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and
* C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */
#endif
}

if (BSP_WARM_START_POST_C == event)
{
/* C runtime environment and system clocks are setup. */

/* Configure pins. */
R_IOPORT_Open (&IOPORT_CFG_CTRL, &IOPORT_CFG_NAME);

#if BSP_CFG_SDRAM_ENABLED

/* Setup SDRAM and initialize it. Must configure pins first. */
R_BSP_SdramInit(true);
#endif
}
}

#if BSP_TZ_SECURE_BUILD

FSP_CPP_HEADER
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();

/* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
{

}
FSP_CPP_FOOTER

#endif

赞(0)
未经允许不得转载:网硕互联帮助中心 » 蓝牙遥控的电子小狗!【1.2 基于瑞萨RA4M2单片机设计的保姆级教程】
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!