ARM⑦——WDT&RTC&PWM&ADC

一、看门狗概述

概述:看门狗,又叫watchdog timer,是一个定时器电路,一般有一个输入,叫喂狗,一个输出到MCU的RST端,MCU正常工作的时候,每隔一端时间输出一个信号到喂狗端,给WDT清零,如果超过规定的时间不喂狗,(一般在程序包飞时),WDT定时超过,就回给出一个复位信号到MCU,是MCU复位。防止MCU死机,看门狗的作用就是防止程序发生死循环,或者说程序跑飞。

工作原理:在系统运行以后也就启动了看门狗的计数器,看门狗就开始自动计数,如果到了一定的时间还不去清看门狗,那么看门狗计数器就会溢出从而引起看门狗中断,造成系统复位。

alt

二、实现流程

  1. 原理图

    无原理图,看门狗属于CPU内部机制

  2. 芯片手册

    watchDog Timer

alt >alt 计数器计算:PCLK 100M/ (249+1)/128 = 3125; 1s复位 则设置WDDAT寄存器的值为3125

WTCNT 0x10060008 [15:8] 当前计数器的值

初始化函数

#define WTCON (*(volatile unsigned int *)0x10060000)
void watchdog_init()
{
    WTCON = (WTCON & (~(0xff << 8))) | (0xf9 << 8);
    WTCON = WTCON | (0x1 << 5);
    WTCON = WTCON | (0x3 << 3);
    WTCON = WTCON & (~(0x1 << 2));
    WTCON = WTCON | (0x1 << 0);

    WTCNT = (WTCNT & (~(0xffff << 0))) | 3125;
}

喂狗函数

#define WTCNT (*(volatile unsigned int *)0x10060008)
void wdt_feed(int value)
{
    WTCNT = value;
}

三、RTC实时时钟

RTC概述:RTC实时时钟,记录年月日时分秒等数据,有备用电源,设备关闭后RTC也能正常记录时间。

alt

秒寄存器

alt

分寄存器

alt

//RTC
#define RTCCON (*(volatile unsigned int *)0x10070040)
#define BCDSEC (*(volatile unsigned int *)0x10070070)
#define BCDMIN (*(volatile unsigned int *)0x10070074)
#define BCDHOUR (*(volatile unsigned int *)0x10070078)
#define BCDDAYWEEK (*(volatile unsigned int *)0x10070080)
#define BCDDAY (*(volatile unsigned int *)0x1007007C)
#define BCDMON (*(volatile unsigned int *)0x10070084)
#define BCDYEAR (*(volatile unsigned int *)0x10070088)


void rtc_init()
{
    RTCCON |= 1 << 0;
    BCDYEAR = 0x111;
    BCDMON = 0x11;
    BCDDAY = 0x11;
    BCDDAYWEEK = 0x2;
    BCDHOUR = 0x12;
    BCDMIN = 0x30;
    BCDSEC = 0x11;
    RTCCON &= ~(1<<0);

}

void rtc_display()
{
    uart_sendChar(((BCDYEAR>>8)&0xf) + '0');  
    uart_sendChar(((BCDYEAR>>4)&0xf) + '0');
    uart_sendChar(((BCDYEAR>>0)&0xf) + '0');
    uart_sendChar('-');
    uart_sendChar(((BCDMON>>4)&0x1) + '0');
    uart_sendChar(((BCDMON>>0)&0xf) + '0');
    uart_sendChar('-');
    uart_sendChar(((BCDDAY>>4)&0x3) + '0');
    uart_sendChar(((BCDDAY>>0)&0xf) + '0');
    uart_sendChar('-'); 
    uart_sendChar(((BCDHOUR>>4)&0x3) + '0');
    uart_sendChar(((BCDHOUR>>0)&0xf) + '0');
    uart_sendChar(':');
    uart_sendChar(((BCDMIN>>4)&0x7) + '0');
    uart_sendChar(((BCDMIN>>0)&0xf) + '0'); 
    uart_sendChar(':');
    uart_sendChar(((BCDSEC>>4)&0x7) + '0');
    uart_sendChar(((BCDSEC>>0)&0xf) + '0');
    uart_sendChar('\r');
    uart_sendChar('\n');
}

四、PWM

  • PWM:脉冲宽度调制
  • 占空比:就是输出的pwm中,高电平保持的事件与该pwm的时钟周期的时间之比

alt

​ 上述例子,TCNTB寄存器 存放的初值用来倒数 ,当TCNTB 比 TCMPB寄存器值大时,输出的是低电平,当TCNTB倒数到小于等于TCMPB时 电平反转为高电平,直到计数到0,之后又开始新一轮的倒数计数,从而实现PWM和占空比的控制。

利用无源蜂鸣器测试PWM

  1. 原理图

    PWM BEEP ——》MOTOR_PWM ——》XpwmTOUT0/LCD_FRM/GPD0_0

  2. 芯片手册

    寄存器 地址 bit位 备注
    GPD0CON 0x114000A0 [3:0] 0x2 = TOUT0 使能复用PWMTOUT功能
    TCNTB0 0x139D000C [31:0] 300 倒数计数器预装载值
    TCMPB0 0x139D0010 [31:0] 150 比较值
    TCFG0 0x139D0000 [7:0] 249 (250 - 1) timer0、1的预分频值
    TCFG1 0x139D0004 [3:0] 0100 = 1/16 timer0的分频值
    TCON 0x139D0008 [3] 1 = auto reload timer0自动装载
    [2] 1 = output 使能pwm输出
    [1] 1 or 0 = update 启动 / 关闭更新,与[0]启动定时器不能同时开启
    [0] 1 or 0 启动 、关闭定时器
  3. 编程

#define GPD0CON (*(volatile unsigned int *)0x114000A0)
#define TCFG0   (*(volatile unsigned int *)0x11400000)
#define TCFG1   (*(volatile unsigned int *)0x11400004)
#define TCON    (*(volatile unsigned int *)0x11400008)
#define TCNTB0  (*(volatile unsigned int *)0x1140000C)
#define TCMPB0  (*(volatile unsigned int *)0x11400010)

//初始化蜂鸣器 pwm
void pwm_beep_init()
{
    GPD0CON = (GPD0CON & (~(0xf << 0))) | (0x2 << 0);
    TCFG0 = TCFG0 & (~(0xff << 0)) | (249 << 0);
    TCFG1 = TCFG0 & (~(0xf << 0)) | (0x4 << 0);
    TCON = (TCON & (~(0xf << 0))) | (0xe << 0);
    
    TCNTB0 = TCNTB0 | 300;
    TCMPB0 = TCMPB0 | 150;

}

void beep_start()
{
    TCON = TCON & ~(0x1 << 1);
    TCON = TCON | (0x1 << 0);
}

五、ADC

1、原理图

ADC——》VR1——》XadcAIN3

2、芯片手册

XadcAIN3

寄存器 地址 bit 备注
ADCCON 0x126C0000 [16] 0x1 12位的A/D转换位(位数越高精度越高)
[15] --- 获取转换是否结束
[14] 0x1 使能预分频
[13:6] 0x1 预分频值
[2] 0x0 普通模式
[1] 0x0 失能阅读模式
[0] 0x1 开始读取数据(不能与[1]同时打开),搭配[15]一起使用
ADCDLY 0x126C0008 [15:0] --- 读取延时,配合ADCCON[1]使用
ADCDAT 0x126c000c [11:0] --- ADC转换的值
ADCMUX 0x126c001c [3:0] 0010 选择AIN3

3、编程

//ADC
#define ADCCON (*(volatile unsigned int *)0x126c0000)
#define ADCDAT (*(volatile unsigned int *)0x126c000c)
#define ADCMUX (*(volatile unsigned int *)0x126c001c)

void adc_init()
{
    ADCCON = ADCCON | (0x1 << 16);  //12位数据
    ADCCON = ADCCON | (0x1 << 14);  //允许预分频
    ADCCON = ADCCON & (~(0xff << 6)) | (132 << 6);  //132+1预分频值
    ADCCON = ADCCON & (~(0x1 << 2));    //正常工作模式
    ADCCON = ADCCON & (~(0x1 << 1));    //disables start

    ADCCON = ADCCON & (~(0x3 << 0)) | (0x3 << 0);
}

int adc_read()
{
    ADCCON = ADCCON | (0x1 << 0);       //开始转换
    while(ADCCON&(0x1<<15) == 0);       //未转换完成
    
    return (ADCDAT & (0xfff << 0));

}