(PCB印制电路板]单片机实验报告

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

(PCB印制电路板)单片
机实验报告
目录
实验一、单片机间的多机通信 0
实验二、I2C总线应用技术 (8)
实验三、层次原理图设计 (12)
实验四、元件封装的创建 (15)
实验五、自动布局 (17)
实验六、开关控制LED (21)
实验七、中断计数器 (24)
实验八、UART (29)
实验一、单片机间的多机通信
(1)实验题目
采用C语言实现单片机间的多机通信。

实现内容:三个51单片机进行多机通信。

一个单片机用于温度的采集(可采用可变电阻模拟温度值),一个单片机用于控制8个LED灯循环显示,显示的时间间隔从主机中获得,主机用于发送温度的大小值及循环显示的时间给从机。

(2)实验目的
●掌握proteus和软件环境——keilC的联机调试过程
●掌握基于ARM c编程基础
(3)实验设备
1.Proteus 8 Professional 仿真开发环境;
2.Keil uVision4
(4)实验步骤
1.1打开Proteus 8,选择isis绘制电路图,点击p添加元件AT89C51, BUTTON, CAP, CAP-ELEC, CRYSTAL, RES.
1.2绘制电路图如图所示:
2.1打开Keil uVision5,new project和new file
2.2编写代码:(c语言)
/***********************************
*实验一
*主机
*发送循环显示时间和温度值给从机
*
************************************/
#include<reg51.h>
#include<string.h>
#define _SUCC_ 0x0f//数据传送成功
#define _ERR_ 0xf0//数据传送失败
#define uchar unsigned char
#define uint unsigned int
uint Time[]={0,1,2,3,4,5,6,7}; //循环显示时间间隔(s)uint T[] = {22,33,66,77,88,99};
sbit KEY1=P3^3;
sbit KEY2=P3^5;
uchar count =0;
//延时1ms函数
void delay_1ms(uint t)
{
uint y;
while(t--)
for(y=110;y>0;y--);
}
//串口初始化函数
void serial_init()
{
TMOD=0x20; //定时器1工作于方式2
TH1=0xfd;
TL1=0xfd; //波特率为9600
PCON=0;
SCON=0xd0; //串口工作于方式3
TR1=1; //开启定时器
TI=0;
RI=0;
}
//发送数据函数
void SEND_data(uint *Buff)
{
TI=0; //发送数据长度
TB8=0; //发送数据帧
P2 = Buff[count];
SBUF=Buff[count];
while(!TI);
TI=0;
count++;
count=count%5;
}
//向指定从机地址发送数据
void ADDR_data(uchar addr, uint *Buff) {
uchar temp=0xff;
while(temp!=addr) //主机等待从机返回其地址作为应答信号{
TI=0; //发送从机地址
TB8=1; //发送地址帧
SBUF=addr;
while(!TI);
TI=0;
RI=0;
while(!RI);
temp=SBUF;
RI=0;
}
SEND_data(Buff);
}
//main函数
void main()
{
serial_init();
while(1)
{
if(KEY1==0)
{
delay_1ms(5);
if(KEY1==0)
{
while(!KEY1);
ADDR_data(0x01,Time);
}
}
if(KEY2==0)
{
delay_1ms(5);
if(KEY2==0)
{
while(!KEY2);
ADDR_data(0x02,T);
}
}
}
}
/*********************************** *实验一
*从机1
*接收主机发送的温度值
*
************************************/ #include<reg51.h>
#include<string.h>
#include<intrins.h>
#define addr 0x02//从机2的地址#define _SUCC_ 0x0f//数据传送成功#define _ERR_ 0xf0//数据传送失败#define uint unsigned int
#define uchar unsigned char unsigned char Buff[20];//数据缓冲区uchar flag = 0; //请求标志
sbit cs = P1^0;
sbit clk = P1^1;
sbit dio = P1^2;
//串口初始化函数
void serial_init()
{
TMOD=0x20; //定时器1工作于方式2 TH1=0xfd;
TL1=0xfd; //波特率为9600
SCON=0xd0; //串口工作于方式3 TR1=1; //开启定时器
TI=0;
RI=0;
}
//----------------------------------
//延时
//----------------------------------- void delay(uint x )
{
uint i;
while(x--) for(i = 0;i <120; i++); }
//-------------------------------------- //得到ad转结果
//------------------------------------- uchar get_ad_result()
{
uchar i,dat1 = 0,dat2 = 0;
cs = 0;
dio = 1;
_nop_();_nop_();
clk = 1;
_nop_();_nop_();
clk = 0;dio = 1; _nop_();_nop_(); clk = 1; _nop_();_nop_();
clk=0 ;dio = 0; _nop_();_nop_(); clk=1 ;dio = 1; _nop_();_nop_(); clk=0;dio = 1; _nop_();_nop_(); for(i= 0;i<8;i++)
{
clk=1; _nop_();_nop_();
clk=0; _nop_();_nop_();
dat1 = dat1<<1|dio;
}
for(i= 0;i<8;i++)
{
dat2 = dat2 |((uchar)(dio)<<i); clk=1; _nop_();_nop_();
clk=0; _nop_();_nop_();
}
cs =1;
return (dat1 == dat2)? dat1:0;
}
//------------------------------------
//主函数
//-------------------------------------
void main()
{
uint i = 0 ,j=0;
uchar temp = 0,temp2 = 0;
uchar aa = 0xff;
serial_init();
while(1)
{
SM2 = 1; //接收地址帧
aa = 0xff;
while(aa!=addr) //从机等待主机请求自己的地址{
RI=0;
while(!RI)
{
temp = get_ad_result();//温度采集结果
if(temp != temp2)
P2 = temp;
}
temp2 = temp;
aa=SBUF;
RI=0;
}
TI=0; //一旦被请求,从机返回自己地址作为应答,等待接收数据TB8=0;
SBUF=addr;
while(!TI);
TI=0;
SM2=0; //接收数据帧
RI=0;
while(!RI);
Buff[i]=SBUF; //数据帧
RI=0;
P2 = Buff[i];//查看接收到的数据
}
}
/***********************************
*实验一
*从机2
*接收主机发送的循环显示时间
*
************************************/
#include<reg51.h>
#include<string.h>
#include<intrins.h>
#define addr 0x01//从机2的地址
#define _SUCC_ 0x0f//数据传送成功
#define _ERR_ 0xf0//数据传送失败
#define uint unsigned int
#define uchar unsigned char
uint code sTable[]={0,10,20,40,60,80,100,150}; uint Buff[20];//数据缓冲区
uchar light = 0x00;
uint speed = 0;
uint tcount = 0;
//串口初始化函数
void serial_init()
{
TMOD=0x20; //定时器1工作于方式2
TH1=0xfd;
TL1=0xfd; //波特率为9600 PCON=0;
SCON=0xd0; //串口工作于方式3 TR1=1; //开启定时器
TI=0;
RI=0;
}
//---------------------------------- //延时
//----------------------------------- void T0_INT() interrupt 1
{
if(tcount++ < speed) return;
tcount = 0;
P1 = light;
light = _crol_(light , 1);
}
//------------------------------------ //主函数
//------------------------------------- void main()
{
uint i = 0 ,j=0;
uint m;
uchar aa = 0xff;
serial_init();
IE = 0X82;
TR0 = 1;
while(1)
{
SM2=1; //接收地址帧
aa=0xff;
while(aa!=addr) //从机等待主机请求自己的地址
{
RI=0;
while(!RI);
aa=SBUF;
RI=0;
}
TI=0; //一旦被请求,从机返回自己地址作为应答,等待接收数据TB8=0;
SBUF=addr;
while(!TI);
TI=0;
SM2=0; //接收数据帧
RI=0;
while(!RI);
m=SBUF; //数据帧
RI=0;
speed = sTable[m];
P2=m; //查看接收到的数据
light = 0x01;
}
}
2.3 compile file,生成 .HEX文件
(5)实验小结
本次实验,
实验二、I2C总线应用技术
(1)实验题目
实验题目:采用C语言完成I2C的通信。

实现内容:放置两个I2C芯片,一个是24C01存储器,一个是24C02,分别向两个芯片中写入0~16,17~33。

然后读出相加并将值写入单片机相关单元。

(2)实验目的
掌握proteus和软件环境——keilC的联机调试过程
(3)实验设备
1.Proteus 8 Professional 仿真开发环境;
2.Keil uVision5
(4)实验步骤
1.1打开Proteus 8,选择isis绘制电路图,点击p添加元件AT89C51, BUTTON, CAP, CAP-ELEC, CRYSTAL, RES.
1.2绘制电路图如图所示:
2.1打开Keil uVision5,new project和new file
2.2编写代码:(c语言)
//----------------------------------------------------
//实验二、I2C总线应用技术
//采用C语言完成I2C的通信。

//实现内容:放置两个I2C芯片,一个是24C01存储器,一个是24C02,
//分别向两个芯片中写入0~16,17~33。

然后读出相加并将值写入单片机相关单元。

//---------------------------------------------------
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define NOP4(){_nop_();_nop_();_nop_();_nop_();}
sbit SCL = P3^0;
sbit SDA = P3^1;
uchar *ptr=0x30; //保存相加结果的地址
//-------------------------------------
//延时函数
//-------------------------------------
void delayms(uint x)
{
uchar i;
while (x--)for(i=0;i<120;i++);
}
//--------------------------------
//开始
//--------------------------------
void start()
{
SDA = 1; SCL = 1; NOP4(); SDA = 0; NOP4(); SCL =0;
}
//-----------------------------------------
//停止
//-----------------------------------------
void stop()
{
SDA = 0; SCL =0 ;NOP4();SCL = 1; NOP4(); SDA = 1;
}
//----------------------------------------------
//写完等待从器件应答
//----------------------------------------------
bit ACK(void)
{
uchar i; SCL = 1; NOP4(); i = SDA; SCL = 1; NOP4(); SCL = 0; if(i==1) return 0;
else return 1;
}
//-----------------------------------------
//读完发送停止读的信号
//-----------------------------------------
void NO_ACK()
{
SDA = 1; SCL = 1; NOP4(); SCL = 0;SDA = 0;
}
//-------------------------------------
//写字节
//-------------------------------------
void I2C_writebyte(uchar d)
{
uint i;
for(i=0;i<8;i++)
{ d <<= 1;SDA = CY;_nop_();SCL = 1;NOP4();SCL = 0; } ACK();
}
//---------------------------------
//读字节
//--------------------------------
uchar I2C_readbyte()
{
uchar i , d;
for(i=0;i<8;i++)
{ SCL = 1;d <<= 1;d |=SDA;SCL = 0; }
return d;
}
//--------------------------
//写地址及数据
//--------------------------
void I2C_write_addr(uchar sl, uchar addr, uchar dat)
{
start();
I2C_writebyte(sl);
I2C_writebyte(addr);
I2C_writebyte(dat);
stop();
delayms(10);
}
//---------------------------
//读当前地址的数据
//-----------------------------
uchar I2C_read_current(uchar s)
{
uchar d;
start();
I2C_writebyte(s+0x01);
d = I2C_readbyte();
NO_ACK();
stop();
return d;
}
//---------------------------
//读指定地址的数据
//-----------------------------
uchar I2C_read_random(uchar sl,uchar addr)
{
uchar d;
start();
I2C_writebyte(sl);
I2C_writebyte(addr);
d = I2C_read_current(sl);
return d;
}
//---------------------------
//主函数
//---------------------------
void main()
{
uchar i;
uint dat1=0;
uint dat2=17;
uchar sl[]={0xa0,0xaE};
for(i = 0;i < 16; i++)
{
I2C_write_addr(sl[0],i,dat1);
I2C_write_addr(sl[1],i,dat2);
dat1++;
dat2++;
}
for(i = 0;i < 16; i++)
{
dat1=I2C_read_random(sl[0],i);
dat2=I2C_read_random(sl[1],i);
dat2 = dat2+dat1;
*ptr = dat2;
P2 = dat2;
delayms(100);
ptr++;
}
while(1);
}
2.3 compile file,生成 .HEX文件
2.4proteus下运行仿真,暂停,查看cpu内存:
(6)实验小结
本次实验目的:掌握I2C总线应用技术,用单片机通过总线控制2块I2C芯片。

难点是通过程序模拟I2C的时序,开始、应答、传送字节。

但一条总线挂了多个I2C芯片时,需要设定每个芯片的地址,主机在发送的帧中包含地址信息(A2A1A0).
实验三、层次原理图设计
(1)实验题目
完成P126的电路图设计。

要求采用层次电路图的方式进行设计,并进行电气规则检查,生成元件报表、网络表。

(2)实验目的
掌握proteus层次原理图设计
(3)实验设备
1.Proteus 8 Professional 仿真开发环境;
(4)实验步骤
原电路原理图
1. 创建子电路
经过分析,决定对选取其中的一部分电路作为子电路进行层次设计。

使用子电路工具建立层次图。

2.将光标放置在子图上,点右键,并选择菜单命令“Goto Child Sheet”(默认组合键为“Ctrl+C”),这时ISIS加载一空白的子图页
3.编辑子电路
4.子电路编辑完后,选择菜单命令【Design】→【Goto Sheet】,这时出现如图8-50所示对话框,选择“Root sheet1”,然后单击“OK”按钮,即使ISIS回到主设计图页。

5.电气规则检查
6.生成网络表。

(5)实验小结
本次实验,ISIS支持层次设计。

对于一个较大、较复杂的电路图,不可能一次完成,也不可能将这个电路图画在一张图纸上,更不可能由一个人单独来完成。

利用层次电路图可以大大提高设计速度,也就是将这种复杂的电路图根据功能划分为几个模块,由不同的人员来分别完成各个模块,做到多层次并行设计。

实验四、元件封装的创建
(1)实验题目
完成实验二的PCB设计,要求进行元件的布局、手工布线。

(2)实验目的
掌握proteus和软件环境——keilC的联机调试过程
(3)实验设备
1.Proteus 8 Professional 仿真开发环境;
(4)实验步骤
1.实验二电路原理图
2.生成网络表
3.在ARES中导入网络表文件。

4.在自动布局之前需要先画一个板框。

在ARES左侧的工具箱中选择,从主
窗口底部左下角下拉列表框中选择“Board Edge”(黄色),在适当的位置画一个矩形,作为板框。

5.自动布局
6.手工布线。

(6)实验小结
Proteus软件提供自动布局和手工布局两种方式。

在进行布局时,推荐使用自动布局和手工布局相结合的方式,即先使用自动布局,然后进行手工调整
实验五、自动布局
(1)实验题目
完成实验一的PCB设计。

要求进行元件的布局、自动布线。

(2)实验目的
掌握proteus和软件环境——keilC的联机调试过程
(3)实验设备
1.Proteus 8 Professional 仿真开发环境;
(4)实验步骤
1.实验一电路原理图:
把单片机的时钟复位电路设计成子电路
2.为元器件指定相应的封装。

2.1元件封装的创建
本次实验用到的8段数码管在package library 中找不到封装,自己画一个该器件的封装并添加进user库。

2.2给数码管指定自己的封装
3.检查电器规则
4.生成元件列表(略)
5.自动布局
6.手动调整
7.自动布线
(5)实验小结
Proteus ARES基于网格的布线既灵活又快速,并能使用任何导线密度或孔径宽度,以90°或45°在1~8层上布线。

在电子世界最近的PCB软件评论上排列A类。

布线参数设置好后,就可以利用Proteus ARES提供的布线器进行自动布线了,执行自动布线的方法如下。

选择【Tools】→【Auto Router】菜单项,或者单击工具按钮即可弹出如图9-38所示的自动布线设置对话框
本次实验难点在于元器件封装的创建和指定。

因为proteus版本不同,功能有所变动,课件上的方法有些不适用,后来经过查找资料最后成功完成。

实验六、开关控制LED
(1)实验题目
ARM的P0.8口接按钮,P0.9口接LED等,通过开关控制LED的亮、灭。

(2)实验目的
●掌握proteus和软件环境——keilC的联机调试过程
●掌握基于ARM c编程基础
(3)实验设备
1.Proteus 8 Professional 仿真开发环境;
2.Keil uVision4
(4)实验步骤
1.1打开Proteus 8,选择isis绘制电路图,点击p添加元件LPC2101
1.2绘制电路图如图所示:
2.1打开Keil uVision5,new project和new file
2.2编写代码:(c语言)
/**************************************************
*实验六、开关控制LED
* ARM的P0.8口接按钮,P0.9口接LED等,通过开关控制LED的亮、灭。

***************************************************/
#include<LPC21XX.H>
#define P0_1 0X100 ;
//----------------------
//延时
//----------------------
void delay()
{
unsigned volatile long i ;
for(i = 0;i < 10000; i++);
}
int main()
{
int p01state;
PINSEL0 = 0;
IO0DIR = 0X000200;
IO0SET = 0X000200;
while(1)
{
p01state = IO0PIN &P0_1 ;
if(p01state == 0)
{
IO0CLR = 0X000200;
delay();
}
else {
IO0SET = 0x000200;
delay();
}
}
}
2.3 compile file,生成 .HEX文件
(5)实验小结

ARM需要初始化很多的功率寄存器和引脚设置的寄存器这在STC的51上都是没有的但是在启动代码里都帮你做好了编程的时候只需要对引脚和外设进行初始化就可以如果需要改变运行的频率再去该功率寄存器。


首选你需要设置引脚的功能模块ARM很多引脚功能都是复用的你要用UART或者普通IO的功能必须要设置引脚的功能模块在UART中你也需要设置UART相应的寄存器比如速度模式等寄存器另外如果你选用新的一些ARM芯片例如CORTEX M 系列的那么你还必须要设置使能这个IOCON GPIO UART功能的时钟
举个例子
sbit led=P2^0; 这句在ARM里就需要首先设置引脚为GPIO功能在设置它为输出功能再给它高电平才能实现

首先来说说PINSEL0和PINSEL1。

因为这个芯片很多引脚是复用的,自然多个功能不可能同时使用,所以就需要选择引脚功能,用的就是这两个寄存器,具体细节就不说了,自己看Datasheet吧…LPC2103中PINSEL0管PIN0.0-PIN0.15,PINSEL1管PIN0.16-PIN0.31。

值的设定基本是
这两个寄存器的复位值都是0×00000000,也就是所有引脚复位都是做GPIO用的。

再下来是GPIO的控制寄存器了。

IOPIN 管脚值寄存器。

可以用来读取当前的管脚值,赋值也可以控制管脚输出。

IOSET 用来管脚置位的寄存器。

写0无效,写1管脚置高电平。

IOCLR 用来管脚清除的寄存器。

写0无效,写1管脚置低电平。

IODIR 管脚方向控制寄存器。

0对应输入,1对应输出。

复位值:0×00000000(所有管脚复位为输入)

#define LED1 (1<<17)
ARM中操作单个IO不能逐位操作只能通过与运算和或运算操作
(1<<5)代表1向左移五位二进制0000 0001 左移5位后变成0010 0000这样就GPIO 的第5位输出1其他输出0向外输出
通过GPIO_PB|=(1<<5)来只把第5位置1,不影响其他位。

通过GPIO_PB&=~(1<<5)来清零第5位
同理可以用于其他IO操作
实验七、中断计数器
(1)实验题目
将三个按钮接到LPC2106的三个中断EINT0、EINT1和EINT2上,通过LED显示显示中断发生的次数。

当外部中断0有效时,进行加1操作;当外部中断1有效时,进行减1操作;当外部中断2有效时,进行清零操作。

(2)实验目的
●掌握proteus和软件环境——keilC的联机调试过程
●掌握基于ARM c编程基础
(3)实验设备
1.Proteus 8 Professional 仿真开发环境;
2.Keil uVision4
(4)实验步骤
1.1打开Proteus 8,选择isis绘制电路图,点击p添加元件LPC2101
1.2绘制电路图如图所示:
2.1打开Keil uVision5,new project和new file
2.2编写代码:(c语言)
/*************************
*
*实验七、中断计数器
*将三个按钮接到LPC2106的三个中断EINT0、EINT1和EINT2上,通过LED显示显
示中断发生的次数。

*当外部中断0有效时,进行加1操作;当外部中断1有效时,进行减1操作;当外部中断2有效时,进行清零操作。

*************************/
#include"LPC21XX.h"
#define uint32 int
#define uint8 unsigned char
#define SPI_CS 0x00000100 /* P0.8 */
#define SPI_DATA 0x00000040 /* P0.6 */
#define SPI_CLK 0x00000010 /* P0.4 */
#define SPI_IOCON 0x00000150 /* SPI接口的I/O设置字也就是将P0.4、P0.6、P0.6设置为输出*/
#define LEDCON 0x00002000 //P0.13
int count =5 ; //初始计数值
void DelayNS(uint32 dly)
{
uint32 i;
for(;dly>0;dly--)
for(i=0;i<25000;i++);
}
/* 向74HC595发送一个字节数据;发送数据时,高位先发送*/ void HC595_SendData(uint8 dat)
{
uint8 i;
IOCLR0=SPI_CS; // SPI_CS=0;
for(i=0;i<8;i++) // 发送8位数据
{
IOCLR0=SPI_CLK;// SPI_CLK=0
/* 设置SPI的DATA输出值*/
if((dat&0x80)!=0)
IOSET0=SPI_DATA;
else
IOCLR0=SPI_DATA;
dat=dat<<1;
IOSET0=SPI_CLK; // SPI_CLK=1
} IOSET0=SPI_CS; // SPI_CS=1, 输出显示数据
}
void __irq IRQ_Eint1(void)
{
uint32 i;
//i=VICIRQStatus;
i=IO0PIN;
if((i&LEDCON)==0)
{IOSET0=LEDCON; }
else{ IOCLR0=LEDCON;}
count--;
while((EXTINT&0x02)!=0) //等待外部中断信号恢复为高电平(若信号为低,则中断标志会一直置位)
{
EXTINT=0x02;
}
VICVectAddr=0x00;
//在终端发生时硬件会自动将对应的地址VICVectAddr?装入VICVectAddr,故退出时要清零
/*在退出中断服务程序时要清零相应外设的中断标志,以及VICVectAddr寄存器,为响应下次中断作好准备。

*/
}
void __irq IRQ_Eint2(void)
{
uint32 i;
//i=VICIRQStatus;
i=IO0PIN;
if((i&LEDCON)==0)
{IOSET0=LEDCON; }
else{ IOCLR0=LEDCON;}
count = 0;
while((EXTINT&0x04)!=0) //等待外部中断信号恢复为高电平(若信号为低,则中断标志会一直置位)
{
EXTINT=0x04;
}
VICVectAddr=0x00;//在终端发生时硬件会自动将对应的地址VICVectAddr?装入VICVectAddr,故退出时要清零
/*在退出中断服务程序时要清零相应外设的中断标志,以及VICVectAddr寄存器,为响应下次中断作好准备。

*/
}
void __irq IRQ_Eint0(void)
{
uint32 i;
//i=VICIRQStatus;
//*p = i;
i=IO0PIN;
if((i&LEDCON)==0)
{IOSET0=LEDCON; }
else{ IOCLR0=LEDCON;}
count++ ;
while((EXTINT&0x01)!=0) //等待外部中断信号恢复为高电平(若信号为低,则中断标志会一直置位)
{
EXTINT=0x01;
}
VICVectAddr=0x00;//在终端发生时硬件会自动将对应的地址VICVectAddr?装入VICVectAddr,故退出时要清零
/*在退出中断服务程序时要清零相应外设的中断标志,以及VICVectAddr寄存器,为响应下次中断作好准备。

*/
}
int main(void)
{
Const uint8
DISP_TAB[16]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x
88,0x83,0xC6,0xA1,0x86,0x8E};
PINSEL0=0xa0000000; //设置所有引脚连接GPIO
PINSEL1=0x00000001;
IO0DIR=LEDCON | SPI_IOCON; //设置SPI控制口为输出
IO0CLR=LEDCON;
IO0SET=LEDCON;
EXTMODE=EXTMODE|0x01;//边缘触发
EXTPOLAR=EXTPOLAR&0x0e; //下降沿触发*/
/****************设置向量中断控制器****************************/
VICIntSelect=VICIntSelect&(~(7<<14));//EINT1、2、0中断分配为IRQ中断
VICVectCntl1=0x20|15; //EINT1中断分配为向量IRQ通道1
VICVectCntl2 = 0x20|16;
VICVectCntl3 = 0x20|14;
VICVectAddr1=(uint32)IRQ_Eint1; //向量IRQ通道1的中断服务程序地址为Eint1_ISR
VICVectAddr2=(uint32)IRQ_Eint2;
VICVectAddr3=(uint32)IRQ_Eint0;
VICIntEnable=(7<<14); //EINT1中断使能
while(1)
{
HC595_SendData(DISP_TAB[count]); //输出LED显示数据
DelayNS(5);
}
return 0;
}//在project选项里面勾选use memory layout from target dialog!
2.3 compile file,生成 .HEX文件
(5)实验小结
➢74HC595简介
引脚说明:
1、Q0…Q7为8位并行数据输出
2、Q7’第9脚,串行数据输出,用于级联
3、MR 第10脚主复位(低电平)
4、SH_CP 第11脚移位寄存器时钟输入
5、ST_CP 第12脚存储寄存器时钟输入
6、OE 第13脚输出有效(低电平)
7、DS 第14脚串行数据输入
➢LPC21XX外部中断输入
概述
LPC2106具有3路外部中断,可以设置为2种类型:
●边沿触发:
上升沿触发
下降沿触发
●电平触发:
高电平触发
低电平触发
➢本次实验用到一些比较难懂的中断寄存器:
●中断选择寄存器(VICIntSelect):
位31 …18 17 … 2 1 0
功能保留A/D转
换器外部
中断3
ARM
内核
—WDT
寄存器中每一位控制着一个中断源,各中断源的位置与中断源列表所示相同。

向某位写入1时,对应中断源产生的中断为FIQ中断,否则为IRQ中断
●向量IRQ中断相关寄存器
向量地址寄存器(VICVectAddr0~15):
该寄存器中存放对应优先级向量IRQ中断服务程序的入口地址。

位7 6 5 [4..0]
功能--EN 中断源序号VICVectCntlx[4:0]:分配给此优先级向量IRQ中断的中断源序号;
VICVectCntlx[5]:该位为1,使能当前优先级的向量IRQ中断。

否则为禁止。

向量控制寄存器(VICVectCntl0~15):
位[31:0]
功能中断服务程序入口地址
➢使用VIC的注意要点
●如果在片内RAM中调试程序,并使用了中断,那么必须将存储器映射控制设置为
内部RAM模式;
●将多个中断源设置为FIQ,将增加中断响应延时,所以建议FIQ中断只有一个中
断源;
●ADS1.2规定在定义中断服务函数时必须加入关键字“__irq”,保证函数返回时
会切换处理器模式;
●在退出中断服务程序时要清零相应外设的中断标志,以及VICVectAddr寄存器,
为响应下次中断作好准备
实验八、UART
(1)实验题目
采用中断实现通过串口0发送“Hello World!”,然后在虚拟终端接收器上查看。

(2)实验目的
●掌握proteus和软件环境——keilC的联机调试过程
●掌握基于ARM UART编程基础
(3)实验设备
1.Proteus 8 Professional 仿真开发环境;
2.Keil uVision4
(4)实验步骤
1.1打开Proteus 8,选择isis绘制电路图,点击p添加元件LPC2101
1.2绘制电路图如图所示:
2.1打开Keil uVision5,new project和new file
2.2编写代码:(c语言)
/*************************
*实验八、UART
*采用中断实现通过串口0发送“Hello World!”,然后在虚拟终端接收器上查看。

*************************/
#include"lPC21XX.H"
/*================================================= ===========
LPC21XX 串口使用接收发送中断
================================================== ============
*/
#define Fosc 11059200 //晶振频率,10MHz~25MHz,应当与实际一至
#define Fcclk (Fosc * 5) //系统频率,必须为Fosc 的整数倍(1~32),且
<=60MHZ
#define Fcco (Fcclk * 4) //CCO 频率,必须为Fcclk 的2、4、8、16 倍,范围156MHz~320MHz
#define Fpclk (Fcclk /4) * 1 //VPB 时钟频率,只能为(Fcclk / 4)的1 ~ 4 倍通常只需要设置Fosc 即可。

需要更改Fcclk 和Fcco 时,参照注释。

#define UART_BPS 9600; //串口波特率
#define uint32 unsigned int
#define uint8 unsigned char
uint8 send_buffer[] = {"Hello world !"};
uint8 msg[] = {"transfer has completed !"};
//----------------------
//延时
//----------------------
void delay()
{
unsigned int i ;
for(i = 0;i < 10000; i++);
}
//---------------------------------
//UART初始化
//---------------------------------
void UART_init()
{
uint32 Fdiv;
PINSEL0 = 0x00000005;
U0LCR = 0X83; //置位除数锁存位
Fdiv = ( Fpclk / 16) / UART_BPS; //根据波特率计算分频
U0DLM = Fdiv / 256;
U0DLL = Fdiv % 256;
U0LCR = 0X03; //清除除数锁存位,并设置工作模式// U0FCR = 0x81; // 使能FIFO,并设置触发点为8字节U0IER = 0x02; // 允许THRE中断
IO0DIR = 0X08;
IO0CLR |= 0X08;
}
//-----------------------------
//UART0发送一个字符
//---------------------------
void UART0_SendByte(uint8 byte)
{
U0THR = byte;
delay();
}
//----------------------------
//UART0发送一串字符
//---------------------------- void UART0_SendBuf(uint8 *p) {
while(*p != '\0')
UART0_SendByte(*(p++));
}
//-------------------------
//UART0中断服务函数
//-------------------------
void __irq IRQ_UART0()
{
uint32 data;
UART0_SendBuf(send_buffer);
U0THR = 0x0d;
UART0_SendBuf(msg);
IO0SET |= 0X08;
data = U0IIR; VICVectAddr = 0x00;
//在终断发生时硬件会自动将对应的地址VICVectAddr?装入VICVectAddr,故退出时要清零
}
//--------------------------------
//主函数
//--------------------------------
int main()
{
UART_init();
VICIntSelect = 0x00000000;
VICVectCntl0 = (0x20|6);
VICVectAddr0 = (int)IRQ_UART0;
VICIntEnable = 1<<6;
}
2.3 compile file,生成 .HEX文件
(5)实验小结
➢UART结构图
➢使用UART前需要设置的寄存器
寄存器名称功能
UnLCR
设置UARTn 的通信格式。

UnFCR
设置UARTn 的接收FIFO 缓冲区。

UnDLL 、
UnDLM
设置UARTn 的通信波特率。

UnIER
设置UARTn 的中断。

U1MCR
Modem 接口设置(只有UART1具有)。

➢ UART 应用示例——操作流程 本次实验用到UART 的THRE 中断,所以在串口初始化的时候 设置U0IER = 0x02;允许THRE 中断。

相关文档
最新文档