题型 | 数量 | 范围 |
---|---|---|
选择题 | 10X2’ - | |
填空题 | 20X1’ | - |
判断题 | don’t know | - |
简答题 | 4X5’ | - |
程序题 | 12’+8’ | - |
-本章主要考小题
-P4页
分为以下几类:
-P5页
嵌入式微处理器 EMPU——————(Embedded Microprocessor Unit)
嵌入式微处理器具有体积小、重量轻、成本低、可靠性高的优点,但是在电路板上必须包括ROM、RAM、总线接口、各种外设等器件,从而降低了系统的可靠性,技术保密性也较差。嵌入式微处理器及其存储器、总线、外设等安装在一块电路板上,称为单板计算机
微控制器(单片机) MCU—————(Microcontroller Unit)
嵌入式微控制器又称单片机,它是将整个计算机系统集成到一块芯片中。嵌入式微控制器一般以某一种微处理器内核为核心,芯片内部集成各种必要功能和外设。
和嵌入式微处理器相比,微控制器的最大特点是单片化,体积大大减小,从而使功耗和成本下降、可靠性提高。微控制器是目前嵌入式系统工业的主流。微控制器的片上外设资源一般比较丰富,适合于控制,因此称微控制器。
DSP处理器 DSP—————————(digital Signal Processor)
DSP处理器对系统结构和指令进行了特殊设计,使其适合于执行DSP算法,编译效率较高,指令执行速度也较高。在数字滤波、FFT、谱分析等方面DSP算法正在大量进入嵌入式领域,DSP应用正从在通用单片机中以普通指令实现DSP功能,过渡到采用嵌入式DSP处理器。
片上系统 SoC——————————(System on Chip)
在一个硅片上实现一个更为复杂的系统,这就是System On Chip(SOC)。用户只需定义出其整个应用系统,仿真通过后就可以将设计图交给半导体工厂制作样品。这样除个别无法集成的器件以外,整个嵌入式系统大部分均可集成到一块或几块芯片中去,应用系统电路板将变得很简洁,对于减小体积和功耗、提高可靠性非常有利。
SoC可以分为通用和专用两类。
注:了解各自的适用范围与区别
发展史概述
计算机系统由硬件和软件组成,在发展初期没有操作系统这个概念,用户使用监控程序来使用计算机。随着计算机技术的发展,计算机系统的硬件、软件资源也愈来愈丰富,监控程序已不能适应计算机应用的要求。于是在六十年代中期监控程序又进一步发展形成了操作系统(Operating System)。发展到现在,广泛使用的有三种操作系统即多道批处理操作系统、分时操作系统以及实时操作系统。
嵌入式操作系统采用实时操作系统
操作系统分类:
备注:
实时操作系统强调实时性、可靠性、灵活性
-P7页 ppt P20页
-P11 ppt P35(目测选择题)
注: 注意了解各自的优缺点,通读留个印象
-简答题X3,小题
-P16页,了解特性
个人科普用,老师只要求了解这两个名词,并且大头考RISC,此段可以忽略
-P17,老师重点提到下面两个
Cortex-M3处理器
该处理器是首款基于ARMv7-M架构的处理器,采用了纯Thumb2指令的执行方式,具有极高的运算能力和中断响应能力。
Cortex-M3主要应用于汽车车身系统,工业控制系统和无线网络等对功耗和成本敏感的嵌入式应用领域
ARM7(系列)
该系列包括ARM7TDMI、ARM7TDMI-S、带有高速缓存处理器宏单元的ARM720T和扩充了Jazelle的ARM7EJ-S。该系列处理器提供Thumb 16位压缩指令集和EmbededICE软件调试方式,适用于更大规模的SoC设计中。
ARM7系列广泛应用于多媒体和嵌入式设备,包括Internet设备、网络和调制解调器设备,以及移动电话、PDA等无线设备。
ppt P17页
字母 | 全写 | 意义 |
---|---|---|
T | Thumb | 支持高密度16位的Thumb指令集 |
D | Debug | 支持片上调试 |
M | Multiplier | 支持64位乘法,内嵌硬件乘法器 |
I | 嵌入式ICE | 支持EmbededICE观察硬件;仿真功能模块,支持片上断点和调试点。 |
S | synthesizable | ARM7TDMI 的可综合(synthesizable)版本(软核),对应用工程师来说其编程模型与ARM7TDMI 一致 |
书P20 ppt P20页,了解三个动作及作用、有点,可能考简答或填空
正常操作过程中,在执行一条指令的同时对下一条(第二条)指令进行译码,并将第三条指令从存储器中取出。
无论处理器处于何种状态,程序计数器R15(PC)总是指向“正在取指”的指令,而不是指向“正在执行”的指令或者正在“译码”的指令。
解:
其他参照ppt与书
-P23页 ppt P24页,可以忽略具体管脚名,主要记住周围的功能与接口,最可能的考法是对着图片填空
-P24页 ppt P28页
两个状态之间的切换并不影响处理器模式或寄存器内容。
注:不考状态切换相关知识,T是CPSR的一个控制位,注意结合下文看,CPSR也是必考点
31个通用32位寄存器
6个32位状态寄存器(目前均只使用了其中的12位)
寄存器R13、R14分别有6个分组的物理寄存器。1个用于用户和系统模式,其余5个分别用于5种异常模式。
寄存器R13通常作为堆栈指针(SP),用于保存待使用的寄存器的内容。
寄存器R14称为链接寄存器(LR),在结构上有两个特殊功能:
寄存器R15称为程序计数器(PC),它指向正在“取指”的指令。
上下文有介绍
-P28页 ppt P34页
-R15
它指向正在“取指”的指令,由于ARM体系结构采用了多级流水线技术,对于ARM指令集而言,PC总是指向当前正在执行指令的下两条指令的地址,即PC的值为当前指令的地址值加8个字节程序状态寄存器。
注:记住每个寄存器是做什么的以及各个位的含义(CPSR)
书 p36 ppt P43
简介
CPSR(当前程序状态寄存器)在任何处理器模式下被访问。它包含了条件标志位、中断禁止位、当前处理器模式标志以及其他的一些控制和状态位。每一种处理器模式下都有一个专用的物理状态寄存器,称为SPSR(备份程序状态寄存器)。当特定的异常中断发生时,这个寄存器用于存放当前程序状态寄存器的内容。
在异常中断退出时,可以用SPSR来恢复CPSR。由于用户模式和系统模式不是异常中断模式,所以他没有SPSR。当用户在用户模式或系统模式访问SPSR,将产生不可预知的后果。
ARM内核包含1个CPSR和5个仅供异常处理程序使用的SPSR。ARM的所有模式共享一个CPSR。CPSR反映当前处理器的状态,其包含:
字符 | 释义 | value |
---|---|---|
N | nagetive | 负或小于 |
Z | Zero | 零 |
C | Carry | 进位或借位拓展 |
V | oVerflow | 溢出标志 |
记住CPSR每个位的作用,老师强调过,可能简答或填空,可参照ppt P44页往后详细了解
-P41页 ppt P49页 记住异常优先级
当多个异常同时发生时,一个固定的优先级决定系统处理它们的顺序。
不考
-4.3-4.6 了解即可
-4.7-4.16 重点
P88页看一看
P89页的特性:
-P112页,老师由此引入一个Bootloader的概念、记住你认为有用的
在嵌入式操作系统中,BootLoader是在操作系统内核运行之前运行。可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。在嵌入式系统中,通常并没有像BIOS那样的固件程序(注,有的嵌入式CPU也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。
Bootloader是嵌入式系统在加电后执行的第一段代码,在它完成CPU和相关硬件的初始化之后,再将操作系统映像或固化的嵌入式应用程序装在到内存中然后跳转到操作系统所在的空间,启动操作系统运行。
操作模式
启动过程,分为两个阶段
-P113页,熟悉这些概念有助于更好的理解PLL与VPB
时钟是计算机系统的脉搏,处理器核在一拍接一拍的时钟驱动下完成指令执行、状态变换等动作。
外设部件在时钟的驱动下进行着各种工作,比如串口数据的收发、A/D转换、定时器计数等。
LPC2000系列微控制器的时钟系统包括四个部分:晶体振荡器、唤醒定时器、锁相环(PLL)和VPB分频器。
图解:
可分为两种模式:
: 唤醒定时器能够确保振荡器和芯片内部硬件电路在处理器开始执行指令之前有足够的时间初始化 。
当给芯片加电或某个事件使芯片退出掉电模式后,振荡器就开始工作,但是需要一段时间来产生足够振幅的信号驱动时钟逻辑。振荡的波形大致如下:
-需要熟悉PLL频率计算
符号 | 说明 | 助记 |
---|---|---|
Fosc | 晶体振荡器的输出频率 | OS clk |
Fcco | PLL电流控制振荡器的输出频率 | current-controlled-output |
Fcclk | PLL最终的输出频率 | cpu-clk |
M | PLLCFG寄存器中MSEL位的倍增器值 | Multiplication |
P | PLLCFG寄存器中PSEL位的分频器值 |
或者忽略书本和ppt上那么多无谓的换算,直接用我们日常的习惯写出输入输出的关系
这里参照课本P134,PPT P87页,P88页有程序和流程图
ppt P81
-P137页,了解VPB分频设置,工作频率的设置
概念:
VPB总线是芯片的内部总线,上面挂接着绝大部分的外设,而这些外设的工作速度相对于ARM内核来说都要慢一些,VPB分频器决定了处理器时钟(cclk)与外设器件所使用的时钟(pclk)之间的关系。
用途:
根据外设时钟与内核时钟的关系,设置对应的VPB值:
void VPBSet(uint32 Fcclk, uint32 Fpclk)
{
uint8 i;
if((Fpclk / (Fcclk / 4)) == 1) //是系统时钟1/4
{
VPBDIV = 0; //写入00
}
else
if((Fpclk / (Fcclk / 4)) == 2) //是系统时钟1/2
{
VPBDIV = 2; //写入10
}
else
if((Fpclk / (Fcclk / 4)) == 4) //和系统时钟相等
{
VPBDIV = 1 //写入01
}
}
不考
此节主要看懂PINSEL寄存器的作用
概述:
LPC2000系列微控制器的大部分管脚都具有多种功能,即管脚复用,但是同一引脚在同一时刻只能使用其中一个功能,通过配置相关寄存器控制多路开关来连接引脚与片内外设。
寄存器描述
LPC2000系列微控制器具有三个32位宽度PINSEL寄存器:
其中PINSEL0和PINSEL1控制端口0,PINSEL2根据芯片的不同控制的端口数量也不同 。
其中PINSEL0共32位,控制P0.0~15这16个端口,2位控制一个端口。
将P0.8、P0.9设置为TxD1、RxD1
通过查阅PINSE0寄存器设置表,得到P0.9和P0.8的控制位为PINSEL0[19:16],当该域设置为[0101] (0x05)时选择 RxD1和 TxD1。
PINSEL0 = 0x05 << 16;
#define BV(x) (1 << (x))
意义:将1左移x位,这样可以非常方便且清晰的控制寄存器的每个位 PINSEL0|=BV(16);//设置P0.8,第16位为1, 0 1 0‘1’
PINSEL0|=BV(18);//设置P0.9,第18为为1, 0‘1’0 1
```
PINSEL0 = (PINSEL0 & 0xFFF0FFFF) | (0x05 << 16);
为什么用以上赋值方式,按之前的方法直接写等于不是更简单?P0.0到P0.15共16个引脚,2个引脚一组,共8组
于是有8个F
F是十六进制,换成二进制就是0000四个二进制位
于是就是8x4=32位
一个F(0000)对应两个引脚,那么一个引脚对应两个二进制位(00)
每个引脚取值范围(00-01-10-11)共四个状态
结合题意,P0.8和P0.9应该是第5组,对应其中第五个F,
按从右到左的顺序,右面两个00代表P0.8的控制位,左边两个00代表P0.9的控制位
这里第五个F为0的意思是一次性设置P0.8和P0.9两个管脚,并保持其他管脚的设置不变
拓展理解:
PIDIR|=0x01; //写1不改变其他位
PISEL&=~0x01: //写0不改变其他位
PIDIR |=0x01与 PIDIR=0x01;
P1DIR|=0x01
是复合值语句,等价于P1DIR=P1DR|0x01,这是个按位或运算,然后再赋值
P1DIR=0x01,就是简单的额一条值语句,
区别就是:
PlSEL&=~0x01 :
写0而不影响其他位,同上,如果我们想写入0而不影响其他位可以利用&=~的复合运算
ppt P43页应用示例
-P179页,这节主要了解几个重要寄存器的配置
IOxPIN
IOxDIR
Tips:(老师上课强调过)
两个寄存器设置区别(P182页)
P183页,主要了解为啥要接上拉电阻:
-P186页,大概率会根据这些内容出一道8分程序题
使用GPIO注意点:
...
PINSEL0 &= 0xFFFFFFFC; //设置管脚连接模块,设置 P0.0为GPIO功能(=00)
IO0DIR | = 0x00000001; //设置P0.0管脚输入输出模式,此处设置为输出(=1)
IO0SET = 0x00000001; //设置P0.0管脚的状态,此处为高电平(IO0SET=1)
...
代码解释:
tips
一般&=经常用于置0的操作中
相反 |=经常用于写1的操作中
示例2 读取P0.0状态
...
uint32 PinStat;
PINSEL0 &= 0xFFFFFFFC; //设置管脚连接模块,设置 P0.0为GPIO功能(=00)
IO0DIR &= 0xFFFFFFFE; //设置P0.0管脚输入输出模式,此处设置为输入(=0)
PinStat = IO0PIN & 0x01; //从IO0PIN读取引脚状态
...
代码解释:
/******************************************************************************
*功能:读取I/O引脚值,并输出控制蜂鸣器
* 使用I/O口输入方式对P0.14经行扫描
******************************************************************************/
#include
#include
#define BEEPCON 0x00000080; /*P0.7引脚,控制蜂鸣器,输出低电平蜂鸣*/
#define P0_14 0x00004000; /*P0.14引脚,获取按键状态*/
/*******************************************************************************
**函数名: main()
**描述: 读取P0.14口的值,并通过P0.7控制蜂鸣器
********************************************************************************/
int main(void) {
int p014State; //自定义一个变量用来获取按键状态
PINSEL0 = 0x00000000; /*设置引脚为GPIO */
IO0DIR = BEEPCON; /*将P0.7设置为输出,其他都为输入 */
IO0SET = BEEPCON; /*使P0.7输出高电平,也就是让他先保持安静 */
p014State = IO0PIN&P0_14; /*获取按键状态 */
while (1) {
/*读取按键状态*/
if(p014State == 1){ //如果按键没按下,P0.14为高电平
IO0SET = BEEPCON; //输出高电平,让他安静
}
else{
IO0CLR = BEEPCON; //输出低电平,让他叫
}
}
}
#include //包含库
#define xxxx xxxx //预定义
/*******************************************************************************
**函数名: main()
**描述: 主程序流程
********************************************************************************/
main(){
PINSELx; //设置管脚模式,如GPIO
IOxDIR; //设置输入输出
IOxSET; //设置初始电平
//以上都为初始化
//下面进入一个无限循环,负责执行操作或者等待中断发生
//可能刚接触的人很难理解这个无限循环,明明在c语言中要避免死循环啊??
//没有这个无限循环,程序执行一次就会结束,从而失去了实时性的意义
while(1){
···//事件在循环中被执行或者在中断处理函数中被执行
}
}
在这里的无限循环中,程序进入一个循环等待判断阶段:-P189页,ppt P61页
-了解中断的基本流程,以及了解相关寄存器功能
-P199页,了解流程图,
-记住两个入口地址
-P224页 ppt P24页,图4.98定时器方框图,熟悉流程
本节主要了解定时器的配置,通过配置定时器,实现小灯定时亮灭(非delay函数)
ppt P62页
-书本P239页,总线配置,几根?,什么时候上拉。对应ppt P67页
概念
SPI总线系统是一种同步串行外设接口,允许MCU与各种外设以串行的方式进行通信、数据交换。
一般使用4条线:
图4.110 SPI总线的配置
如图所示,一个SPI主线可以接多个主机和从机,但是在同一时刻只允许有一个主机操作总线。在数据传输的过程中,总线上只能有一个主机和一个从机通信。在一次传输中,主机总是向从机发送一个 字节数据(MOSI),而从机也总是向主机发送一个字节数据(MISO)。SPI总线时钟总是由主机产生的。
使用SPI接口的注意要点
-书P250页,ppt P95页,了解概念和常识性知识,比如几根总线,总线方式——别吐槽,老师原话
概念:
I2C总线是Philips推出的串行传输总线,它以2根连线实现了完善的双向数据传输,可以极方便地构成多机系统和外围器件扩展系统。
I2C总线的两根线(串行数据SDA,串行时钟SCL)连接到总线上的任何一个器件,每个器件都应有一个唯一的地址,而且都可以作为一个发送器或接收器,此外,器件在执行数据传输的时候也可以被看作主机从机。
典型结构:
在图中,CPUA可以作为该总线上的唯一主机,其他部件都是从机。另一种方式是CPUA和CPUB都作为总线上的主机。
当两个以上的CPU同时发动传输时,只能有一个控制器件能真正控制总线成为主机,并使报文不被破坏,这个过程叫仲裁。与此同时,能同步多个控制器件所产生的时钟信号
SDA和SCL都是双向线路。连接到总线的器件的输出极必须使漏极开路或者集电极开路,都通过一个电流源或上拉电阻连接到正的电源电压,这样才能实现”线与“的功能。当总线空闲时,这两条线路都是高电平。
在标准模式下,总线数据的速度为0~100kbit/s,在高速模式下,可达0-400kbit/s。
总线速率越高,上拉电阻越小。。100kbit/s总线速率,上拉电阻通常使用5.1kΩ。
I2C总线上每传输一个数据位必须产生一个时钟脉冲
-P278页,ppt P3页
-P304页,ppt P45页
特性
LPC2114/2124具有一个AD转换器,LPC2200系列具有两个AD转换器,它们具有如下特性:
描述
A/D转换器的基本时钟由VPB时钟提供。可编程分频器可将时钟调整至逐步逼近转换所需的4.5MHz(最大)。如要要得到10位精度的结果,需要11个A/D转换时钟。
A/D转换器的参考电压来自V3A和VSSA引脚。
ADC转换时钟分频值计算:
ADC使用方法
使用ADC模块时,先要将测量通道引脚设置为AINx功能,然后通过ADCR寄存器设置ADC的工作模式、ADC转换通道、转换时钟(CLKDIV时钟分频值),并启动ADC转换。可以通过查询或中断的方式等待ADC转换完毕,转换数据保存在ADDR寄存器中。
A/D没有独立的参考电压引脚,A/D的参考电压与供电电压连接在一起即3.3V。假定从ADDR寄存器中读到的10位A/D转换结果为VALUE,则对应的实际电压是:
-P311页,熟悉看门狗定时器的功能
void WDT_Init(unit 32 time)
{
WDTC=time; //设置看门狗的溢出时间
WDMOD=0x03; //看门狗定时器定时溢出后,中断且复位
WDFEED=0xaa; //执行喂狗序列启动看门狗
WDFEED=0x55;
}
//看门狗喂狗程序
void FeedDog()
{
IRQDisable();//禁止总断
WDFEED=0xaa;//喂狗序列
WDFEED=0x55;
IRQEnable();//使能中断
}
//看门狗演示程序
#define KEY (1<<20) //按键为P0.20
#define BEEP (1<<7) //蜂鸣器控制引脚
int main()
{
unit32 dly;
PINSEL0=0x00;
PINSEL1=0x00;
IO0DIR=BEEP;
IO0CLR=BEEP; //复位后,蜂鸣器鸣叫一声
for(dly=0;dly<5000;dly++);
IO0SET=BEEP;
WDT_Init(0x1000 0000) //初始化看门狗定时器,溢出产生复位
while(1)
{
while((IO0PIN&KEY)==0); //按下按键,停止喂狗
for(dly=0;dly<100;dly++);
FeedDog();
}
return 0;
}
- 概念
一个嵌入式处理器自己是不能独立工作的,必须给它供电、加上时钟信号、提供复位信号,如果芯片没有片内程序存储器,则还要加上存储器系统,然后嵌入式处理器芯片才可能工作。这些提供嵌入式处理器运行所必须的条件的电路与嵌入式处理器共同构成了这个嵌入式处理器的最小系统。而大多数基于ARM7处理器核的微控制器都有调试接口,这部分在芯片实际工作时不是必需的,但因为这部分在开发时很重要,所以也把这部分也归入最小系统中。
-P360页,大概了解,程序题中要求画出原理图,不需要所有引脚,但是关键引脚需要记住。
前两个是老师给的例程,里面加上了注释
#include
#define CR 0x0D //换行
char ledDown[]={"The LED is down!\n"}; //定义字符串
char ledUp[]={"The LED is up!\n"};
int putchar (int ch) {/* UART输出一个字符 */
if (ch == '\n') {
while (!(U1LSR & 0x20));
U1THR = CR; //输出换行符
}
while (!(U1LSR & 0x20));
return (U1THR = ch);
}
void delay (void) { /* 延时函数 */
unsigned volatile long i,j;
for(i=0;i<60000;i++)
for(j=0;j<5;j++)
;
}
void serialPuts(char *p){/* UART输出字符串 */
while (*p != '\0'){
putchar(*p++);
}
}
int main (void)
{
/*初始化 UART*/
PINSEL0 = 0x00050000;/* 设置P0.8和P0.9为Txd模式(UART1[RxD1&TxD1] 打开UART)*/
PLLCFG=0; //PLL配置寄存器
//PLLCON = 1;//enable PLL
PLLCON=3; //使能并连接PLL
//VPBDIV=0; //写入00,是系统时钟的1/4
VPBDIV=1; //写入01,根据前面可知与系统时间相等
PLLFEED=0XAA;//在有效的馈送之后 激活 PLL
PLLFEED=0X55;
U1LCR = 0x83;/* 8bit data 无奇偶校验,1 bit 停止位,DLAB=1 */
//U1DLM=0 //因为默认为0,所以此段可以省略
U1DLL = 97;/* 当 VPB 15MHz 波特率 9600 */
U1LCR = 0x03;/* DLAB = 0 */
/*结束初始化 UART*/
IO0DIR = 0x000001;/*设置 P0.0 为输出 */
while (1)
{
IO0CLR = 0x000001;//P0.0口输出低电平,点亮LED
serialPuts(ledUp);//串口输出点亮字符串
delay();
IO0SET = 0x000001;//P0.0口输出高电平,熄灭LED
serialPuts(ledDown);//串口输出熄灭字符串
delay();
}
}
写PLLCFG 和PLLCON:启动PLL,但是不连接PLL 到系统内核。 PLLCON = 0x01、 PLLCFG=0x04
保存中断寄存器,关中断
连续写PLLFEED(必须连续,不能被中断) PLLFEED = 0xAA PLLFEED = 0x55
查询PLLSTAT 一直到PLOCK=1
While((PLLSTAT & 0x40) == 0) { Wait; //等待,一直到PLOCK=1 }
写PLLCFG 和PLLCON:
启动PLL,连接PLL 到系统内核。 PLLCON = 0x03、 PLLCFG=0x04
连续写PLLFEED(必须连续,不能被中断) PLLFEED = 0xAA PLLFEED = 0x55
查询PLLSTAT,等待PLOCK=1,PLLE=1,PLLC=1,MSEL4:1 和PSEL1:0(PLLSTAT 的位6-5) 看是否完全符合,如果符合执行下一步,不符合报错。
恢复原来的中断寄存器状态
U1LCR = 0x83;/* 8bit data 无奇偶校验,1 bit 停止位,DLAB=1 */
U1DLM=0 //因为默认为0,所以此段可以省略
U1DLL = 97;/* 当 VPB 15MHz 波特率 9600 */
U1LCR = 0x03;/* DLAB = 0 */
#include
#define LED 0x000001
typedef unsigned int uint32;
typedef unsigned char uint8;
uint8 timer0Times = 0;
//中断服务程序
__irq void timer0_ISR (void) //定时器触发IRQ中断处理函数
{
//中断处理
uint32 i;
timer0Times++; //计数累加,产生一次中断加1
if(timer0Times == 10){ //产生10次中断执行以下操作
i=IO0SET; //读取当前LED控制值
if((i&LED)==0){ //IOPIN是否为0
IO0SET=LED; //若为0,熄灭LED
}else{
IO0CLR=LED; //反之点亮
}
timer0Times = 0; //计数归零
}
T0IR = 1; //定时器0的中断标志清零
VICVectAddr = 0; //向量地址寄存器,中断结束后该寄存器恢复为0 ,
//通知中断处理结束
}
//定时器0初始化
void timer0Init (void) {
T0MR0 = 119999; //设置匹配值
T0MCR = 3; //匹配后复位TC,并产生中断
T0TCR = 1; //启动定时器0,T0TCR计数控制寄存器
VICVectAddr0 = (unsigned long)timer0_ISR; //设置定时器0的中断服务程序地址
VICVectCntl0 = 0x20 | 4; //定时器0分配给向量IRQ通道0,优先级最高
VICIntEnable = 0x00000010; //定时器0中断使能
}
int main(void) {
PINSEL0 = 0; //设置所有引脚为GPIO模式
IO0DIR = LED; //设置P0.0输出
IO0SET = LED; //输出高电平,默认熄灭
timer0Init(); //初始化定时器0
while (1) {
}
}
拓展
程序:
/******************************************************************************
*功能:读取I/O引脚值,并输出控制蜂鸣器
* 使用I/O口输入方式对P0.14经行扫描
******************************************************************************/
#include
#include
#define BEEPCON 0x00000080; /*P0.7引脚,控制蜂鸣器,输出低电平蜂鸣*/
#define P0_14 0x00004000; /*P0.14引脚,获取按键状态*/
/*******************************************************************************
**函数名: main()
**描述: 读取P0.14口的值,并通过P0.7控制蜂鸣器
********************************************************************************/
int main(void) {
PINSEL0 = 0x00000000; /*设置引脚为GPIO */
IO0DIR = BEEPCON; /*将P0.7设置为输出,其他都为输入 */
IO0SET = BEEPCON; /*使P0.7输出高电平,也就是让他先保持安静 */
while (1)
{
/*读取按键状态*/
if((IO0PIN&P0_14) == 1){ //如果按键没按下,P0.14为高电平
IO0SET = BEEPCON; //输出高电平,让他安静
}
else{
IO0CLR = BEEPCON; //输出低电平,让他叫
}
for(i=0;i<1000;i++)
}
return 0;
}
代码解析:
P0.7为输出,P0.14为输入
GPIO寄存器组中一位控制一个引脚(不同于PINSEL寄存器,上文有解释)
P0.7是第8个引脚,所以对应32位中的第8位,32位分为8组,一组4位,第8位在第二组的最后一个即是(1000)对应十六进制的8所以为0x0000 0080
同理P0.14是第十五位控制,对应第四组(0100),对应的十六进制为4,所以为0x0000 4000
嵌入式开发的基本模式如下:
#include //包含库
#define xxxx xxxx //预定义
/*******************************************************************************
**函数名: main()
**描述: 主程序流程
********************************************************************************/
main(){
PINSELx; //设置管脚模式,如GPIO
IOxDIR; //设置输入输出
IOxSET; //设置初始电平
//以上都为初始化
//下面进入一个无限循环,负责执行操作或者等待中断发生
//可能刚接触的人很难理解这个无限循环,明明在c语言中要避免死循环啊??
//没有这个无限循环,程序执行一次就会结束,从而失去了实时性的意义
while(1){
···//事件在循环中被执行或者在中断处理函数中被执行
}
}
在这里的无限循环中,程序进入一个循环等待判断阶段:
当满足if中的条件,也就是按键的状态改变变为低的时候,才会通过IO0CLR寄存器第8位写1,让P0.7输出低电平,从而让蜂鸣器鸣叫。
不符合条件则让他熄灭。