11.S3C2440 中断实验(五)定时器中断实验

发布者:DelightfulGaze最新更新时间:2021-10-14 来源: eefocus关键字:S3C2440  中断实验  定时器中断 手机看文章 扫描二维码
随时随地手机看文章

定时器中断实验

        S3C2440提供了3种时钟:FCLK用于CPU核;HCLK用于AHB总线上的设备,比如存储器控制器、中断控制器、LCD控制器、DMA和USB主机模块,同时也可以在特殊情况下用于CPU核;而PCLK则用于APB总线上的设备,比如看门狗、IIS、IIC、PWM定时器、ADC、UART、GPIO、RTC和SPI等。


        总的来说,AHB总线主要用于高性能模块,APB总线主要用于低带宽的周边外设之间的连接。


        S3C2440定时器的总时钟源为PCLK,首先通过两个8位的预分频器降低频率,定时器0、1共用第一个预分频器,定时器2、3、4共用第二个预分频器;之后预分频器的输出将被第二级的五路选择分频器处理,之后供定时器各自选择。


原理介绍

时钟频率选择

        S3C2440 SoC内部含有5个16位的定时器,分别是timer0、timer1、timer2、timer3、timer4。前四个定时器同时还具有PWM(Pulse Width Modulation)功能,而因为第5个定时器timer4没有外部输出引脚,所以不具备PWM功能。同时需要说明,由于timer0定时器还具有一个死区发生器,所以它可以被用来驱动大电流设备。

在这里插入图片描述

        由上图可知,timer0和timer1共用一个8位的预分频器以降低频率;timer2、timer3和timer4共用另外一个预分频器。从预分频器出来之后,会分别进入第二级的5路选择分频器。5路选择分频器可以选择2分频、4分频、8分频、16分频或者直接使用外部时钟TCLK0/TCLK1。每个定时器都可以从第二级分出来的5种频率中选择各自使用的时钟频率。

        对于预分频器,我们可以通过TCFG0寄存器来进行设置。而对于第二级时钟频率选择,则是通过TCFG1寄存器来选择的。


定时器内部控制逻辑

在这里插入图片描述
在这里插入图片描述

        当时钟分频设置好之后,我们开始研究一下定时器本身的设置。

        首先,我们需要设置初始计数缓存寄存器TCNTBn和初始比较值寄存器TCMPBn,用以分别表示定时器n的初始计数值和初始比较值。

        第二,我们需要设置TCON寄存器使得计数器和比较器的值被加载进内部寄存器TCMPn和TCNTn。

        第三,当启动定时器之后,每来一个时钟周期,TCNTn的值就递减1,同时我们可以通过TCNTOn这个观察寄存器来对当前数值进行观察。

        第四,当TCNTn等于TCMPn时,定时器n的输出管脚TOUTn就会电平反转。

        第五,当TCNTn的值到达0时,TOUTn的输出管脚电平会再次反转;同时如果使能了中断的话,并会触发定时器中断。

        第六,如果通过TCON寄存器设置了自动加载计数值的话,当TCNTn递减到0时,TCMPBn和TCNTBn寄存器的值会被自动装入内部寄存器,从而开始新一轮的定时周期。如果没有设置为自动加载的话,定时器就是一次性的。

        通过上述分析我们可知,我们可以设置TCMPBn和TCNTBn的值,来调整TOUTn管脚输出信号的占空比,从而输出PWM方波,因而这几个可以输出PWM的定时器又叫做PWM定时器。所谓PWM,就是可调制脉冲(Pulse Width Modulation)。


定时器设置

TCFG0寄存器

在这里插入图片描述

我们可以看到,TCFG0[7:0]和TCFG0[15:8]分别控制Prescaler0和Prescaler1这两个一级预分频器,其值域为闭区间[0, 255],分频后的输出值为PCLK / (prescaler value + 1)。由于我们之前设置的PCLK频率为50MHz,所以我们将prescaler value设置为99,方便后续计算,即:


TCFG0 = (99 << 0) | (99 << 8);


TCFG1寄存器

在这里插入图片描述

如上图所示,经过一级预分频器后的时钟接下来会被二级五路选择分频器所分频。具体的五路选择则由TCFG1寄存器来配置。这里我们随便选择1/4分频,即:


TCFG1 = (1 << 16) | (1 << 12) | (1 << 8) | (1 << 4) | (1 << 0);


由于这5个定时器操作都是类似的,下面为简便起见,我们只是用定时器0来进行实验。

由于一级分频为1/100,二级分频为1/4,所以定时器0的时钟频率为50MHz/400 = ‭125000‬ Hz。所以我们下面的计数器就要设置为该值,从而1秒产生一次IRQ中断。


哈哈,希望是美好的,现实是残酷的。


我们通过下一张图片可知计数器TCNTB0只能使用16位,所以它可设置的最大计数值为65535,比我们希望设置的值12500小了一个数量级。所以如果我们想1秒产生一次中断,那么就要修改分频系数,我们二级分频系数采用1/8,这样计数值就变为62500,符合要求。


TCFG1 = (2 << 16) | (2 << 12) | (2 << 8) | (2 << 4) | (2 << 0);


TCNTB0和TCMPB0寄存器

在这里插入图片描述

通过上图可知,我们只用到了TCNTB0和TCMPB0 这两个寄存器的低16位。TCNTB0寄存器中保存的是定时器0的计数初始值,TCMPB0寄存器中保存的是定时器0的比较值。

这里需要强调的一点是,由于定时器4没有输出引脚,即没有PWM功能,所以对应定时器4来说,它没有TCMPB4和TCMP4寄存器。

在定时器工作时,我们可以通过TCNTO0这个观察寄存器,对当前定时器内部TCNT0寄存器中的值进行观察。

我们将计数值设置为62500,比较值设置为其一般,即‭31250‬。


TCNTB0 = 62500;

TCMPB0 = 31250;


TCON寄存器

在这里插入图片描述

这里需要强调几点内容:


第一次启动定时器前,一定要手动将TCNTBn和TCMPBn寄存器的值加载到定时器内部寄存器TCNTn和TCMPn中。那么怎么手动加载呢?以定时器0来举例,就是将TCON寄存器的第1位置1即可。之后在后面启动定时器的时候,还需要将这一位清零。

还要设置当本次计数完毕后,是否自动加载计数值,从而开始下一个计数周期。

还要设置定时器TOUTn管脚的输出电平是否反转。

我们设置定时器0为自动加载,从而周期性的产生中断。代码如下所示:


//停止定时器0

TCON &= (~(0x1F << 0));

//将计数器缓冲和比较器缓冲中的值加载到定时器0内

TCON |= (1 << 1);

TCON &= (~(1 << 1));

//启动自动加载,并启动定时器0

TCON = (1 << 3) | (1 << 0);


这样定时器0就开始工作了,每个1秒产生一次IRQ中断。


中断控制器设置

通过查看中断源我们发现,定时器0对应的INT_TIMER0中断源没有子中断源, 所以我们只需设置INTMSK寄存器即可。

在这里插入图片描述

通过上图可知,INT_TIMER0对应的硬件中断号是10。


INTMSK &= (~(1 << 10));


定时器0的中断处理函数

我们在中断处理函数中只打印一句话,表明定时器中断发生了。


void timer0_irq_handler(void){

        printf("nrtimer0 irq is handled.nr");

}


void irqExpHandler(void) {

//现在处于SVC模式

//我们先获取硬件中断号

unsigned int interruptNum = INTOFFSET;

int subInterruptNum = 0;

printf("nrIRQ Interrupt Number: %dnr", interruptNum);

//按键 按下后为低电平

unsigned int isKeyUp = 0;

int ledNum = -1;

switch(interruptNum){

case 0:

//EINT0中断 s2按键

isKeyUp = (GPFDAT & 0x1);

ledNum = LED1;

break;

case 2:

//EINT2 s3按键

isKeyUp = (GPFDAT & (0x1 << 2));

ledNum = LED2;

break;

case 5:

//EINT8_23 s4按键

isKeyUp = (GPGDAT & (0x1 << 3));

ledNum = LED4;

break;

case 10:

timer0_irq_handler();

break;

case 28:

subInterruptNum = SUBSRCPND & 0x7;

if(SUBSRCPND & 0x1) {

//INT_RXD0

uart0_handle_irq(UART0_RX_IRQ);

}

if(SUBSRCPND & 0x2) {

//INT_RXD0

uart0_handle_irq(UART0_TX_IRQ);

}

if(SUBSRCPND & 0x4) {

//INT_RXD0

uart0_handle_irq(UART0_ERR_IRQ);

}

break;

default:

break;

}

if(ledNum > 0) {

if(isKeyUp) {

//熄灭LED1

led_off(ledNum);

printf("Key is Up.LED%d is turn off.nr", ledNum);

}else {

led_on(ledNum);

printf("Key is Down.LED%d is turn on.nr", ledNum);

}

}

//处理完毕,从源头开始清理中断标志

//注意是写1清零

if(interruptNum == 5) {

EINTPEND = (0x1 << 11);

}

SUBSRCPND = subInterruptNum;

SRCPND = (0x1 << interruptNum);

INTPND = (0x1 << interruptNum);


printf("IRQ Interrupt is Handlednr");

}


char gCh = 'A';

int main(void) {

leds_init();

keys_init_irq();

printf("%snr", "IRQ Test.");

dump_norFlash(80);

timer_init();

timer_start();


while(1) {

printf("%c(0x%02x) ", gCh, gCh);

gCh++;

wait(888888);

}

return 0;

}


实验结果

我们可以看到,每个1秒钟产生一次定时器0 IRQ中断,如下图所示:

在这里插入图片描述

实验相关源文件

timer.c


//timer.c

#include "s3c2440_soc.h"

#include "timer.h"

#include "myprintf.h"


void timer0_irq_handler(void){

printf("nrtimer0 irq is handled.nr");

}


void timer_init(void) {

TCFG0 = (99 << 0) | (99 << 8);

TCFG1 = (2 << 16) | (2 << 12) | (2 << 8) | (2 << 4) | (2 << 0);

TCNTB0 = 62500;

TCMPB0 = 31250;

INTMSK &= (~(1 << 10));

}



void timer_start(void) {

//停止定时器0

TCON &= (~(0x1F << 0));

//将计数器缓冲和比较器缓冲中的值加载到定时器0内

TCON |= (1 << 1);

TCON &= (~(1 << 1));

//启动自动加载,并启动定时器0

TCON = (1 << 3) | (1 << 0);

}


intException.c


//intException.c

#include "myprintf.h"

#include "s3c2440_soc.h"

#include "led.h"

#include "uart.h"

#include "timer.h"


void undExpHandler(unsigned int* undAddr) {

printf("Undefined Instruction(0x%08x) at address(0x%08x) is found!nr",

*undAddr, undAddr);

}


void swiExpHandler(unsigned int swiNum) {

printf("Software Exception is Checked with Number %d(0x%x)nr", swiNum, swiNum);

}


void abortPrefetchExpHandler(unsigned int* abtPrefetchAddr) {

printf("Fetch instruction from address(0x%08x) failed.nr", abtPrefetchAddr);

}


void abortDataExpHandler(unsigned int* abtDataAddr) {

printf("Fetch data failed at address(0x%08x).nr", 

abtDataAddr);

}


void irqExpHandler(void) {

//现在处于SVC模式

//我们先获取硬件中断号

unsigned int interruptNum = INTOFFSET;

int subInterruptNum = 0;

printf("nrIRQ Interrupt Number: %dnr", interruptNum);

//按键 按下后为低电平

unsigned int isKeyUp = 0;

int ledNum = -1;

switch(interruptNum){

case 0:

//EINT0中断 s2按键

isKeyUp = (GPFDAT & 0x1);

ledNum = LED1;

break;

case 2:

//EINT2 s3按键

isKeyUp = (GPFDAT & (0x1 << 2));

ledNum = LED2;

break;

case 5:

//EINT8_23 s4按键

isKeyUp = (GPGDAT & (0x1 << 3));

ledNum = LED4;

break;

case 10:

timer0_irq_handler();

break;

case 28:

subInterruptNum = SUBSRCPND & 0x7;

if(SUBSRCPND & 0x1) {

//INT_RXD0

uart0_handle_irq(UART0_RX_IRQ);

}

if(SUBSRCPND & 0x2) {

//INT_RXD0

uart0_handle_irq(UART0_TX_IRQ);

}

if(SUBSRCPND & 0x4) {

//INT_RXD0

uart0_handle_irq(UART0_ERR_IRQ);

}

break;

default:

break;

}

if(ledNum > 0) {

if(isKeyUp) {

//熄灭LED1

led_off(ledNum);

printf("Key is Up.LED%d is turn off.nr", ledNum);

}else {

led_on(ledNum);

printf("Key is Down.LED%d is turn on.nr", ledNum);

}

}

//处理完毕,从源头开始清理中断标志

//注意是写1清零

if(interruptNum == 5) {

EINTPEND = (0x1 << 11);

}

SUBSRCPND = subInterruptNum;

SRCPND = (0x1 << interruptNum);

INTPND = (0x1 << interruptNum);


printf("IRQ Interrupt is Handlednr");

}


void fiqExpHandler(void) {

printf("FIQ is Detected!nr");

unsigned int isKeyUp = 0;

int offset = -1;

int hardwareIntNum = -1;

printf("EINTPEND(0x%08x)nr", EINTPEND);

printf("SRCPND(0x%08x)nr", SRCPND);

if(EINTPEND & (0x1 << 11)) {

//S4按下或松开 EINT11

isKeyUp = (GPGDAT & (0x1 << 3));

if(isKeyUp) {

//熄灭LED4

led_off(LED4);

printf("Key is Up.LED4 is turn off.nr");

}else {

led_on(LED4);

printf("Key is Down.LED4 is turn on.nr");

}

offset = 11;

//EINT11对应的硬件中断号是5

hardwareIntNum = 5;

}else if(EINTPEND & (0x1 << 19)) {

//S5按下或松开 EINT19

isKeyUp = (GPGDAT & (0x1 << 11));

if(isKeyUp) {

//熄灭LED4

led_off(LED1);

led_off(LED2);

led_off(LED4);

printf("Key is Up.LED1 LED2 LED4 is turn off.nr");

}else {

led_on(LED1);

led_on(LED2);

led_on(LED4);

printf("Key is Down.LED1 LED2 LED4 is turn on.nr");

}

offset = 19;

//EINT19对应的硬件中断号是5

hardwareIntNum = 5;

}else {

printf("Unknown FIQ Interrupt!nr");

}

//从源头开始清理中断标志

//注意是写1清零

if(offset >= 0) {

EINTPEND = (1 << offset);

SRCPND = (1 << hardwareIntNum);

}

printf("FIQ is Handled.nr");

}




void keys_init_irq(void) {

//按键S2对应的GPIO是GPF0

//S3对应的GPIO是GPF2

//S4对应的GPIO是GPG3

//初始化GPF0 GPF2为中断功能,对应EINT2 EINT0

GPFCON &= (~(0x33));

GPFCON |= (0x2 << 4) | (0x2 << 0);

//初始化GPG3为中断功能,对应EINT11

GPGCON &= (~(0x3 << 6));

GPGCON |= (0x2 << 6);

//按键S5对应EINT19, GPG11

GPGCON &= (~(0x3 << 22));

GPGCON |= (0x2 << 22);

//设置GPIO中断触发方式为双边沿触发

EXTINT0 |= (0x7 | (0x7 << 8));

EXTINT1 |= (0x7 << 12);

//设置EINT19的触发方式为双边沿触发

EXTINT2 |= (0x7 << 12); 

//打开GPIO中断屏蔽开关

//对于EINT0~EINT3来说,GPIO控制器这里是始终没有屏蔽中断的。

//我们只需打开EINT11中断屏蔽即可。

EINTMASK &= (~(0x1 << 11));

//打开EINT9中断屏蔽开关

EINTMASK &= (~(1 << 19));

//设置EINT19对应的中断方式为FIQ

//当我们将中断方式设置为FIQ时,中断发生时不会去设置INTPND INTOFFSET

INTMOD |= (1 << 5);

//打开中断控制器对应的中断开关

INTMSK &= (~((1 << 0) | (1 << 2) | (1 << 5)));

}


main.c


//main.c

#include "myprintf.h"

#include "nand.h"

#include "nor.h"

#include "uart.h"

[1] [2]
关键字:S3C2440  中断实验  定时器中断 引用地址:11.S3C2440 中断实验(五)定时器中断实验

上一篇:【S3C2440】第14课、异常与中断之学习笔记
下一篇:11.S3C2440 中断实验(一)und和swi实验

推荐阅读最新更新时间:2024-11-13 10:24

学习笔记--- S3C2440 对NANDFLASH操作原理与测试代码分析
首先来看一下NANDFLASH接口: 图上看出只有数据口和控制口,没有地址线,所以它不能像网卡,SDRAM那样统一寻址,它的操作方法步骤: 1 使能芯片 2 发操作指令(读,写,擦,复位) 3 发操作地址 5 等待忙信号释放(只有读) 6 发送数据(写),接收数据(读) 7 等待忙信号,低电平忙 8 禁能芯片 这些控制信号线都是通过软件设置寄存器,然后硬件自动产生其他控制线的控制信号; 操作信号含义如下: R/B :读/忙状态线 CE : 片选 CLE :发送指令信号 ALE :发送地址信号 WE:写信号 RE:读信号 这里要注意的: 1 数据按字节传输,刚好8位
[单片机]
学习笔记--- <font color='red'>S3C2440</font> 对NANDFLASH操作原理与测试代码分析
S3C2440之ADC分析
一、硬件原理分析 我们从结构图和数据手册可以知道,该ADC模块总共有8个通道可以进行模拟信号的输入,分别是AIN0、AIN1、AIN2、AIN3、YM、YP、XM、XP。那么ADC是怎么实现模拟信号到数字信号的转换呢?首先模拟信号从任一通道输入,然后设定寄存器中预分频器的值来确定AD转换器频率,最后ADC将模拟信号转换为数字信号保存到ADC数据寄存器0中(ADCDAT0),然后ADCDAT0中的数据可以通过中断或查询的方式来访问。对于ADC的各寄存器的操作和注意事项请参阅数据手册。 开发板通过一个10K的电位器(可变电阻)来产生电压模拟信号,然后通过第一个通道(即:AIN0)将模拟信号输入ADC。左图中的Aref表示AD的参
[单片机]
linux 2.6.32 在arm9(s3c2440)平台的移植2 -- Kconfig和Makefile
在ubuntu上按照无数帖子无数文档搞了半天qt环境还有eclipse,最后才发现这些都是无关紧要的东西,首先能在ARM核心板上移植linux才是应该先实现的,自己瞎搞了半天移植,对着make menuconfig的复杂树型选项和添加代码迷糊不已,到了晚上下班才猛然醒悟一切都是因为自己kconfig和makefile的关系不明白,才在原地犯迷糊的。 自己的理解 + 网摘, 参考: http://www.cnblogs.com/sirsunny/archive/2004/12/15/77506.html http://blog.csdn.net/windriver_hf/archive/2010/04/16/5493622.as
[单片机]
(6)s3c2440用I2C接口访问EEPROM
在前面阅读理解了I2C的官方协议文档后,就拿s3c2440和EEPROM来验证一下. 本来是想用s3c2440的SDA和SCL管脚复用为GPIO来模拟的,但在没有示波器的情况下搞了一周,怎么都出不来,最后还是放弃了.甚至参考了linux下i2c-algo-bit.c和i2c-gpio.c,依然没调出来.如果有示波器,可能很快就能找到原因,现在完全不知道问题出在哪里.其实想用GPIO模拟I2C的目的很简单,以一种简单而又深刻的方式来理解I2C. 既然这条路暂时没法走,退而求其次,用s3c2440的I2C接口来访问EEPROM,只要按照datasheet的来做,基本上不用考虑时序咯. 从s3c2440和AT24
[单片机]
s3c2440裸机-I2c编程-3-i2c程序框架
1.iiC设备的功能 很显然,IIC控制器提供了传输数据的能力,至于数据有什么含义,IIC控制器并不知道,数据的含义有外部i2c从设备,我们需要阅读芯片手册,才知道IIC控制器应该发出怎样的数据。 下图是AT24cxx的操作方法: 2.I2c程序框架 显然我们的程序应该分为两层(IIC设备层,IIC控制器层),框架如下图所示: 最上层是i2c_test层,用来对i2c的功能进行测试和验证。 第2层是i2c设备层,用来对具体某一型号的从设备进行i2c读写 第3层是通用i2c控制器层,用来提供对具体某一型号的i2c主控进行管理操作 最底层是i2c控制器具体的型号层 在通用i2c控制层,我们提供一个统一的接口i2c_tran
[单片机]
<font color='red'>s3c2440</font>裸机-I2c编程-3-i2c程序框架
s3c2440 --跑马灯 C+汇编代码
/*led_asm_c.c*/ #define rGPFCON (*(volatile unsigned *)0x56000050) //Port F control #define rGPFDAT (*(volatile unsigned *)0x56000054) //Port F data #define rGPFUP (*(volatile unsigned *)0x56000058) //Pull-up control F //GPFCON 8口的 extern int delay(int time); /*声明汇编函数*/ int main() { /*设置 GPFCON*/ rGPFCON &= 0x00f
[单片机]
s3c2440裸机-电阻触摸屏-1-电阻触摸屏原理
一、电阻触摸屏原理 触摸屏包含上下叠合的两个透明层,一般覆盖在lcd表面,两个透明层是由均匀的电阻介质组成,如下图。 当触摸屏表面受到的压力(如通过笔尖或手指进行按压)足够大时,顶层与底层之间的薄膜会产生接触,此时会形成x方向和y方向的坐标。那么x,y坐标的值是怎么得来的呢?本质上就是通过ADC转换得来的。详解如下: 触摸屏的等效电路可以看成如下图: 计算触点的X,Y坐标分为如下两步(见下图): 1.计算Y坐标: 在Y+电极施加驱动电压Vdrive, Y-电极接地,由于上下两层膜形成触点,X+做为触点的引出端,测量得到接触点的电压,触点电压与Vdrive电压之比等于触点Y坐标与屏高度之比。如下图: 2.计算X坐标:
[单片机]
STM8库函数开发手册(2) //中断定时器4
第一部分 中断控制器库 itc.c 1.ITC_GetCPUCC() //读取CC寄存器 u8 u8_value;u8_value = ITC_GetCPUCC(); 2.ITC_DeInit() //恢复ITC相关寄存器到默认值 3. ITC_GetSoftIntStatus() //返回CC寄存器中的软件中断优先级位(I1,I0)的值 u8 u8_value;u8_value = ITC_GetSoftIntStatus(); 4. ITC_SetSoftwarePriority(IrqNum,PriorityValue) //设置指定中断源的软件优先级 其中IrqNum中断源定义: 其中Priori
[单片机]

推荐帖子

麻醉安全度智能监护仪研制成功
从重庆市信息产业局获悉,一项用于提高临床麻醉监护安全性的麻醉安全度智能监护仪日前在重庆工学院研制成功,这一成果有望提高外科手术中使用麻醉手段的安全程度。麻醉是众多外科手术中必须的条件和前提,在全身麻醉手术中,病人在手术中发生知晓意识的比率为1%至2%,麻醉程度不够会造成病人心理不愉快,产生手术恐惧情绪,还会对医生产生不信任感和逆反心理,但麻醉用药过量则更危险。因此,手术麻醉操作既要使病人在手术过程中的意识处于完全消失状态,又要防止麻醉用药过量,降低医疗费用和减少并发症等。重
黑衣人 工控电子
物联网项目 集锦 2:看看你想动手做哪个?
十五.使用ArduinoIDE的ESP8266气象站十六.土壤湿度传感器和Arduino十七.汽车倒车雷达电路十八.Arduino金属探测器十九.数字电容式触摸传感器arduino接口二十.水流量传感器YF-S201Arduino接口二十一.颜色传感器TCS3200Arduino接口二十二.Myoware肌肉传感器与Arduino接口二十三.Arduino的自动风扇速度控制电路二十四.室内空气质量传感器Ren
Jacktang DigiKey得捷技术专区
AD采集分压电阻的选择
单片机AD采集测量范围0~2.56V,现在要测量一个24V~30V的锂电池电压,打算分压,然后AD采集,请问分压电阻如何选择呢?试了好几组电阻值,测出的电压值都比实际电压偏高好多差到0.4~0.5V了,不知该如何选择?程序没有问题,单片机也没有问题,使用精准电压源芯片提供2.5V电压,AD采集值计算结果很准,只是用电阻分压AD采集值就会差很多。还有就是如果是和电阻精度有关,为什么用万用表测出来也和理论计算值接近,唯独AD采集结果偏高好多?AD采集分压电阻的选择 直接用AD测一个不分压的电压
gxp790953623 单片机
为什么需要多寄存器访问指令?
ldr/str每周期只能访问4字节内存,如果需要批量读取、写入内存时太慢,解决方案是stm/ld举例(ubootstart.S537行)stmiasp,{r0-r12}将r0存入sp指向的内存处(假设为0x30001000);然后地址+4(即指向0x30001004),将r1存入该地址;然后地址再+4(指向0x30001008),将r2存入该地址······直到r12内容放入(0x3000130),指令完成。一个访存周期同时完成13个寄
灞波儿奔 微控制器 MCU
51的例程
本帖最后由leo121于2014-5-1021:21编辑 不知道有没有人发过,从keil下载的51的例程顶一下吧。支持下~~
leo121 51单片机
请教反激开关电源的问题
各位老师,请教反激开关电源的问题UC3842主控芯片的反激开关电源,这个红框内的起什么作用?箭头指的是MOS管么,参数怎么选型?请教反激开关电源的问题软起动,芯片的数据手册上有。。【箭头指的是MOS管么,参数怎么选型?】箭头所指是小功率双极型三极管,上面一个是PNP型,下面一个是NPN型。这两个小功率双极型三极管,差不多所有小功率管都可以用,要求不高。例如8550和8050就可以。【这个红框内的起什么作用?】要想弄清楚红框内电路作用,必须结合该
Knight97538 电源技术
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
更多往期活动

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved