资讯详情

嵌入式arm(五)裸机编程之简单的使用{看门狗}{PWM}{ADC}快速练习

使用开发板:FS4412,Soc:Exynos内核型号4412:cortex-A9,架构:armv7; 文件:开发板原理图,Soc数据手册; 环境:文件编写与编译:Linux;下载:超级终端hypertrm;串口下载 编译器:交叉编译器arm

文章目录

    • 一 看门狗定时器
      • 1 看门狗定时器是什么?
        • 1.1 什么是门狗?
        • 1.2 看门狗有什么用?
      • 2 使用门狗
        • 2.1 查硬件电路
        • 2.2 查寄存器
        • 2.3 编程
    • 二 PWM驱动无源蜂鸣器
      • 1 粗略提一点概念
      • 2 查硬件电路
      • 3 查寄存器
      • 4 编程
    • 三 ADC的简单使用
      • 1 简单描述
      • 2 查原理图
      • 3 查寄存器
      • 4 编程

一 看门狗定时器

1 看门狗定时器是什么?

1.1 什么是门狗?

如果我们按照教科书来学习,里面的概念就足够我们吃一天了。当我们做发展时,我们应该注意一个简短而快速的。不要把那些无用的东西整理出来。如果你默地写下教科书上的概念,你可以写下代码吗?严肃的人仍然阅读教科书。 还有,不要整整喂狗。本来学习就够麻烦了,要想狗,还要联系定时器。你累吗?

1.2 看门狗有什么用?

(1) 到时候复位不是闹事吗? 啊,我在时间到了之前就把定时器的值改了,不会到触发复位的条件,好吧。 (2) 怎么改? 我在时间到来之前把定时器改成了初始值,也就是说,让它重新开始计时,我也定期改变,让定时器一直计时,但不能达到设定的时间,也不会重置。 (3) 实现了哪些功能: 跑飞:就是程序不知道跑到哪里去了,不受控制,不做任何相应,卡死也是一种跑飞; (4) 对于那些在没有监控的情况下运行的程序,不知道什么时候可能异常,不能及时复位;现在有了看门狗,设定时间计时;定期恢复用户代码中的计数值,防止复位程序;当用户程序异常运行时,离开用户程序的看门狗计时器到达设定值,恢复正常运行状态; (5) 因此,看门狗的到点复位是程序正常运行时的癌症,程序运行时的救星;

2 使用门狗

2.1 查硬件电路

看门狗定时器是soc工作时不需要引脚: 在这里插入图片描述

2.2 查寄存器

如图所示,8-15位设置第一系列分频,3-4位选择第二级分频,第五位控制看门狗的开关,第二位控制是否中断,第0位设置到达时间是否复位,即可选择时间中断或时间重启。这一次,我们只选择重启; 从第一个框图可以看出,第0-15位设置计数器的最大值wdt是递减计时器;

2.3 编程

下图的程序中,开启了看门狗但是没用复原操作,只放了流水灯,现象为到达设定时间后程序复位,由于程序是烧录到内存中的,所以直接复位导致程序丢失;流水灯全灭无现象;

/* main.c */ #include "led.h" #include "wdt.h" void init() { 
          led_init();  wdt_init(); } int main() { 
          init();  while(1)  { 
           streamled();///流水灯;  }  return 0; } 

恢复操作添加到下图的主程序中,程序不再复位,流水灯一直在运行;

/* main.c */ #include "led.h"#include "wdt.h"
void init()
{ 
        
	led_init();
	wdt_init();
}
int main()
{ 
        
	init();
	while(1)
	{ 
        
		streamled();
		delay();
		delay();
		delay();
		wdt_re;//复原操作
	}
	return 0;
}
/* wdt.c */
#include "wdt.h"

void wdt_init()
{ 
        
	//设置一级250分频,
	WTCON&=~(0xff<<8);
	WTCON|= (249 <<8);
	//设置二级128分频;
	WTCON&=~(0x3<<3);
	WTCON|= (0x3<<3);
	//分频后频率为3125hz;计数器值为15625,即定时5s;
	//设置计时器初值;
	wdt_re;
	//使能reset
	WTCON|=1;
	//开启
	WTCON|=1<<5;
}
/* wdt.h */
#ifndef _WDT_H_
#define _WDT_H_

#define uint unsigned int
#define uchar unsigned char

#define WTCON *((volatile uint *)0x10060000)
#define WTCNT *((volatile uint *)0x10060008)

#define WT_VALUE 15625

#define wdt_re WTCNT=WT_VALUE

void wdt_init();

#endif
/* led.c */
#include "led.h"

void delay()
{ 
        
	int i=0xfffff;
	while(i--);
}
void led_init()
{ 
        
	//设置GPX1_0引脚为输出功能,将GPX1CON的0-3位设置为0x01
	GPX1CON &= ~(0xf << 0);  //将0-3位清0
	GPX1CON |=  (0x1 << 0);  //将0-3设置为0x1

	GPF3CON &= ~(0xff << 16);  //将16-23位清0
	GPF3CON |=  (0x11 << 16);  //将16-23设置为0x11
}
void streamled()
{ 
        
		led3on;
		delay();
		led3of;
		delay();
		led4on;
		delay();
		led4of;
		delay();
		led5on;
		delay();
		led5of;
		delay();
}
/* led.h */
#ifndef _LED_H_
#define _LED_H_

#define GPX1CON *((volatile unsigned int *)0x11000c20)
#define GPX1DAT *((volatile unsigned int *)0x11000c24)
#define GPF3CON *((volatile unsigned int *)0x114001e0)
#define GPF3DAT *((volatile unsigned int *)0x114001e4)

//设置GPX1_0引脚输出1
#define led3on GPX1DAT |= (0x1 << 0) //将第0位设置为1
#define led3of GPX1DAT &=~(0x1 << 0) //将第0位清0
#define led4on GPF3DAT |= (0x1 << 4) 
#define led4of GPF3DAT &=~(0x1 << 4) 
#define led5on GPF3DAT |= (0x1 << 5) 
#define led5of GPF3DAT &=~(0x1 << 5) 

void led_init();
void delay();
void streamled();
#endif

二 PWM驱动无源蜂鸣器

1 粗略提一点概念

上图中占空比就是200/1000=0.2或者说20%; 用通用的定时器可以实现PWM的波形输出,但是不低级的芯片都有专门的PWM外设,只需要设置寄存器就可以产生PWM波形; 无源蜂鸣器需要一个频率波来实现振动,才能发声;(有源蜂鸣器只需要通电就可以响)

2 查硬件电路

引脚是GPD0_0, 用的是pwm0;

3 查寄存器

设置为定时器输出; 设置第一级分频; 设置第二级分频; 控制寄存器,这里只用到低4位;第0位是开启和关闭,第1位进行TCNTB和TCMPB的更新,第2位选择是否翻转电平,第3位设置是否自动重载计数;

4 编程

/* main.c */
#include "led.h"
#include "pwm.h"
int main()
{ 
        
	led_init();
	beep_init();
	pwm_init();
	while(1)
	{ 
        
		streamled();//流水灯;
		pwm_set(20);//设置占空比
		pwmon();//开启
		delay();//响这么久
		pwmof();//关闭
	}
	return 0;
}

/* pwm.c */
#include "pwm.h"
void beep_init()
{ 
        
	GPD0CON&=~0XF;
	GPD0CON|=0X2;
}
void pwm_init()
{ 
        
	//设置GPD0_0为pwm输出
	GPD0CON = GPD0CON & ~(0XF << 0) | (0X2 << 0);
	//分频 -->200000HZ
	TCFG0 = TCFG0 & ~0XFF | 150;
	TCFG1 = TCFG1 & ~0XF  | 0X1;
	//设置计数器寄存器的值 
	TCNTB0 = 100;
	//设置比较寄存器的值(占空比)
	TCMPB0 = 50;
}
void pwmon()
{ 
        
	//手动更新计数器和比较寄存器的值
	TCON = TCON & ~0XF | 0XA;
	//启动定时器
	TCON = TCON & ~0XF | 0X9;
}
void pwmof()
{ 
        
	TCON&=~0x1;
}
void pwm_set(int a)
{ 
        
	TCMPB0=a;
	TCON&=~0xf;
	TCON|=0xa;
}
#ifndef _LED_H_
#define _LED_H_

#define GPD0CON *((volatile unsigned int *)0x114000a0)
#define TCFG0 *((volatile unsigned int *)0x139D0000)
#define TCFG1 *((volatile unsigned int *)0x139d0004)
#define TCON *((volatile unsigned int *)0x139d0008)
#define TCNTB0 *((volatile unsigned int *)0x139d000c)
#define TCMPB0 *((volatile unsigned int *)0x139d0010)

void pwm_init();
void beep_init();
void pwm_set(int);
void pwmon();
void pwmof();
#endif

三 ADC的简单使用

1 简单描述

在学习初期,ADC一般用来读电压,也就是开发板上电位器的电压,概念和原理没啥好说的,只要会配置寄存器,读到电压值即可,就已经能够应付初期大部分的代码任务,在程序中把电压值和其他模块联合起来实现用电位器控制的效果;本次来看使用一路ADC读一个电位器电压的程序示例; 大致流程为: 1、分频 2、设置分辨率 3、开启转换 4、读转换结果

2 查原理图

3 查寄存器

第0位开启adc转换,第1位通过读操作来启动转换,第2位设置工作模式或者省电模式,6-13位设置分频,14位设置是否使能分频,15位是转换完成标志,16位设置10bit或者12bit;

adc数据寄存器,从这里读; adc通路选择

4 编程

/* main.c */
#include "led.h"
#include "pwm.h"
#include "adc.h"
void delay()
{ 
        
	int i=0xfffff;
	while(i--);
}
int main()
{ 
        
	led_init();
	beep_init();
	pwm_init();
	adc_init();
	while(1)
	{ 
        
		streamled();
		adc_ctrl(adc_read());//在这里控制pwm的占空比
		pwmon();
		delay();
		pwmof();
	}
	return 0;
}
/* adc.c */
#include "adc.h"

void adc_init()
{ 
        
	ADCMUX=3;//选择通道3
	ADCCON&=~(1<<16);
	ADCCON|= (1<<14);
	ADCCON&=~(0xff<<6);
	ADCCON|= (19<<6);
	ADCCON&=~(1<<2);
	ADCCON&=~(1<<1);
}
int adc_read()
{ 
        
	ADCCON|=0X1;//开启转换;
	while(!(ADCCON&(1<<15)));//等待转换完成;
	return (ADCDAT&0x3ff);//返回读到的10bit结果;
}
void adc_ctrl(int data)
{ 
        
	pwm_set(data/10);//10bit最大为1024;data/1024就是现在电位器电压值所占最大电压的比,乘以100就能用来当作占空比,大约等于data/10;
}
/* adc.h */
#ifndef _ADC_H_
#define _ADC_H_
#include "pwm.h"

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

void adc_init();
int adc_read();
void adc_ctrl(int);

#endif

标签: wt0040集成电路

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台