瑞萨e2studio.21--看门狗WDT
概述
WDT(Watchdog Timer)和IWDT(Independent Watchdog Timer)都是微控制器中的看门狗定时器,它们的主要功能是在系统发生故障时触发重置,以确保系统能够自动恢复。但它们之间存在一些区别:
时钟源:WDT通常使用系统时钟作为时钟源,而IWDT使用独立的内部低速时钟源。因此,IWDT不依赖于系统时钟,即使系统时钟失效,IWDT仍能正常工作。
供电:WDT和系统共享电源,而IWDT通常拥有独立的电源。这意味着当系统电源出现问题时,IWDT仍可以继续工作。
控制和配置:WDT通常提供更多的控制和配置选项,如可编程超时时间、预分频器等,而IWDT的配置可能较为简单。
应用场景:WDT适用于需要更多控制和配置选项的场景,而IWDT适用于需要独立于系统时钟和电源的场景,例如对系统稳定性和安全性要求较高的应用。
可靠性:由于IWDT使用独立的时钟源和电源,其可靠性通常优于WDT。
总之,WDT和IWDT虽然都是看门狗定时器,但在时钟源、供电、控制和配置等方面存在区别。选择使用WDT还是IWDT取决于具体应用的需求和设计考虑。
最近在弄ST和瑞萨RA的课程,需要RA样片的可以加群申请:6_15061293 。
视频教学
https://www.bilibili.com/video/BV1fg4y1L75m/
瑞萨e2studio(22)--看门狗WDT
csdn课程
csdn课程更加详细。
https://edu.csdn.net/course/detail/36131
样品申请
https://www.wjx.top/vm/wBbmSFp.aspx#
完整代码下载
https://download.csdn.net/download/qq_24312945/87750334
硬件准备
首先需要准备一个开发板,这里我准备的是芯片型号R7FA4M2AD3CFP的开发板:
新建工程
工程模板
保存工程路径
芯片配置
本文中使用R7FA4M2AD3CFP来进行演示。
工程模板选择
时钟配置
开发板上的外部高速晶振为12M,需要修改XTAL为12M.
uart配置
点击Stacks->New Stack->Driver->Connectivity -> UART (r_sci_uart)。
uart属性配置
设置e2studio堆栈
e2studio的重定向printf设置
C++ 构建->设置->GNU ARM Cross C Linker->Miscellaneous去掉Other linker flags中的 “–specs=rdimon.specs”
printf输出重定向到串口
打印最常用的方法是printf,所以要解决的问题是将printf的输出重定向到串口,然后通过串口将数据发送出去。
注意一定要加上头文件#include <stdio.h>
#include <stdio.h>
fsp_err_t err = FSP_SUCCESS;
volatile bool uart_send_complete_flag = false;
void user_uart_callback (uart_callback_args_t * p_args)
{
if(p_args->event == UART_EVENT_TX_COMPLETE)
{
uart_send_complete_flag = true;
}
}
#ifdef __GNUC__ //串口重定向
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
err = R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&ch, 1);
if(FSP_SUCCESS != err) __BKPT();
while(uart_send_complete_flag == false){}
uart_send_complete_flag = false;
return ch;
}
int _write(int fd,char *pBuffer,int size)
{
for(int i=0;i<size;i++)
{
__io_putchar(*pBuffer++);
}
return size;
}
RTC配置
点击Stacks->New Stack->Driver->Timers -> Realtime Clock(r_rtc)。
RTC属性配置
WDT配置
点击Stacks->New Stack->Monitoring -> Watchdog(r_wdt)。
WDT属性配置
R_WDT_Open()函数原型
可以用R_WDT_Open()函数进行初始化和开启WDT。
/* Open the module. */
err = R_WDT_Open(&g_wdt0_ctrl, &g_wdt0_cfg);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
R_WDT_Refresh()函数原型
可以用R_WDT_Refresh()函数进行喂狗操作。
/* Refresh before the counter underflows to prevent reset or NMI. */
err = R_WDT_Refresh(&g_wdt0_ctrl);
assert(FSP_SUCCESS == err);
R_WDT_CounterGet()函数原型
可以用R_WDT_CounterGet()函数获取当前的计数值。
/* Read the current WDT counter value. */
err = R_WDT_CounterGet(&g_wdt0_ctrl, &wdt_counter);
assert(FSP_SUCCESS == err);
WDT周期设定
通过查阅数据手册,可以得知WDT使用的时钟为PCLKB。
在本案例中,使用的PCLKB时钟为25MHz。
WDT从PCLKB运行,依据上文的设定,PCLKB周期如下所示。
参数 | 值 |
---|---|
PLCKB | 25MHz |
分频 | PLCK/8192 |
超时周期 | 16384 cycles |
WDT时钟频率 | 25MHz / 8192 = 3051.7578 Hz |
单周期时间 | 1 / 2929.6875 Hz = 327.68us |
溢出时间 | 341.33 us * 16384 cycles = 5.3687 seconds |
上述可以看到在该设置下的溢出时间为5.59s,那么1s的计数为1s/341.33 us=2930。
WDT计数周期
WDT计数是从最高一直减到0,当到0时候触发复位。
注意事项
如果使用J-Link调试器进行调试的话需要加上这一句话。
R_DEBUG->DBGSTOPCR_b.DBGSTOP_WDT = 0;
演示效果
设置每过1s打印一次当前时间,分别设置喂狗和不喂狗,结果如下。
延迟1s的计数为1s/327.68 us=3052,打印为13337,由于是向下计数,16384-3052=13332,符合计算值。
当不执行喂狗时候,计数值到0时会进行复位,2个复位之间为5.4s,符合计算的5.3687s。
完整代码
/* Initialize the RTC module*/
err = R_RTC_Open(&g_rtc0_ctrl, &g_rtc0_cfg);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
/* Set the RTC clock source. Can be skipped if "Set Source Clock in Open" property is enabled. */
R_RTC_ClockSourceSet(&g_rtc0_ctrl);
/* R_RTC_CalendarTimeSet must be called at least once to start the RTC */
R_RTC_CalendarTimeSet(&g_rtc0_ctrl, &set_time);
/* Set the periodic interrupt rate to 1 second */
R_RTC_PeriodicIrqRateSet(&g_rtc0_ctrl, RTC_PERIODIC_IRQ_SELECT_1_SECOND);
/* Open the module. */
err = R_WDT_Open(&g_wdt0_ctrl, &g_wdt0_cfg);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
/* In register start mode, start the watchdog by calling R_WDT_Refresh. */
err = R_WDT_Refresh(&g_wdt0_ctrl);
assert(FSP_SUCCESS == err);
printf("starting up !\n");
uint32_t wdt_counter = 0U;
while(1)
{
if(rtc_flag)
{
/* Read the current WDT counter value. */
err = R_WDT_CounterGet(&g_wdt0_ctrl, &wdt_counter);
assert(FSP_SUCCESS == err);
printf("wdt_counter=%d\n",wdt_counter);
rtc_flag=0;
/* Refresh before the counter underflows to prevent reset or NMI. */
err = R_WDT_Refresh(&g_wdt0_ctrl);
assert(FSP_SUCCESS == err);
}
}
最后
以上的代码会在Qqun里分享。Qqun:615061293。
或者关注『记帖』,持续更新文章和学习资料!