实验任务
嵌入式计算机系统将独立按键以及独立开关作为输入设备,七段数码管作为输出设备。实现以下功能:
1) 点击BTNC 按键时,计算机读入一组16 位独立开关状态作为一个二进制数据,并将该二进制数的低8 位对应的二进制数值0 或1 显示到8 个七段数码管上。
2) 点击BTNU 按键时,计算机读入一组16 位独立开关状态作为一个二进制数据,并将该16 进制数据各位数字对应的字符0~F 显示到低4 位七段数码管上(高4 位七段数码管不显示)。
3) 点击BTND 按键时,计算机读入一组16 位独立开关状态作为一个二进制数据,并将该数据表示的无符号十进制数各位数字对应的字符0~9 显示到低5 位七段数码管上(高3 位七段数码管不显示)。
要求用程序控制和中断两种方式实现
程序控制:
#include "stdio.h"
#include "xil_io.h"
#include "xgpio_l.h"
int main()
{
char button;//0x10,0x1,0x4
Xil_Out8(0x40020004,0x13); //设置按键为输入
Xil_Out16(0x40000004,0xffff); //设置开关为输入
Xil_Out8(0x40010004,0x0); //设置位码为输出
Xil_Out8(0x4001000c,0x0); //设置段码为输出
while(1)
{
while((Xil_In8(0x40020000)&0x13)!=0) //读按键输入
{
button = Xil_In8(0x40020000)&0x13;
while((Xil_In8(0x40020000)&0x13)!=0);
xil_printf("The pushed button's code is 0x%x\n",button);
if(button == 0x1) //按键C
{
char segtable[2]={0xc0,0xf9}; //段码表
char segcode[8]={0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0}; //显示缓冲区
short poscode[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //位码表
while((Xil_In8(0x40020000)&0x13)==0)
{
for(int i=0;i<8;i++)
{
short key = Xil_In16(0x40000000);
for(int digit_index=0; digit_index<8; digit_index++)
{
segcode[7-digit_index]=segtable[(key>>(digit_index))&0x1];
}
Xil_Out8(0x40010000,poscode[i]);
Xil_Out8(0x40010008,segcode[i]);
for(int j=0;j<10000;j++); //延时控制
}
}
}
else if(button == 0x2) //按键U
{
char segtable[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //段码表
char segcode[4]={0xc0,0xc0,0xc0,0xc0}; //显示缓冲区
short poscode[4]={0xf7,0xfb,0xfd,0xfe}; //位码表
while((Xil_In8(0x40020000)&0x13)==0)
{
for(int i=0;i<4;i++)
{
short key = Xil_In16(0x40000000);
for(int digit_index=0; digit_index<4; digit_index++)
{
segcode[3-digit_index]=segtable[(key>>(4*digit_index))&0xf];
}
Xil_Out8(0x40010000,poscode[i]);
Xil_Out8(0x40010008,segcode[i]);
for(int j=0;j<10000;j++); //延时控制
}
}
}
else if(button == 0x10) //按键D
{
char segtable[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //段码表
char segcode[5]={0xc0,0xc0,0xc0,0xc0,0xc0}; //显示缓冲区
short poscode[5]={0xef,0xf7,0xfb,0xfd,0xfe}; //位码表
while((Xil_In8(0x40020000)&0x13)==0)
{
for(int i=0;i<5;i++)
{
unsigned short key = Xil_In16(0x40000000);
for(int digit_index=0; digit_index<5; digit_index++)
{
segcode[4-digit_index]=segtable[key%10];
key = key/10;
}
Xil_Out8(0x40010000,poscode[i]);
Xil_Out8(0x40010008,segcode[i]);
for(int j=0;j<10000;j++); //延时控制
}
}
}
}
}
return 0;
}
中断:
#include "xil_io.h"
#include "stdio.h"
#include "xgpio_l.h"
#include "xintc_l.h"
#include "xtmrctr_l.h"
#define RESET_VALUE 10000
void Seg_TimerCounterHandler();
void BtnHandler();
void SwitchHandler();
void My_ISR()__attribute__((interrupt_handler));//总中断服务雅序
char segtable[16] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
char segcode[8]={0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0};//缓冲区
short poscode[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
int j = 0;
int k = 0;
int main()
{
Xil_Out32(XPAR_AXI_GPIO_1_BASEADDR+XGPIO_TRI2_OFFSET,0x0);//设段码输出方式
Xil_Out32(XPAR_AXI_GPIO_1_BASEADDR+XGPIO_TRI_OFFSET,0x0);//设位码为输出方式
Xil_Out32(XPAR_AXI_GPIO_2_BASEADDR+XGPIO_TRI_OFFSET,0x13);//设地BUTTON方输入方式
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR+XGPIO_TRI_OFFSET,0xffff);//设地Switch方输入方式
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR+XGPIO_IER_OFFSET,XGPIO_IR_CH1_MASK);//打开开关中断
Xil_Out32(XPAR_AXI_GPIO_2_BASEADDR+XGPIO_IER_OFFSET,XGPIO_IR_CH1_MASK);//打开按键中断
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR+XGPIO_GIE_OFFSET,XGPIO_GIE_GINTR_ENABLE_MASK);//允许GPIO0中断输出
Xil_Out32(XPAR_AXI_GPIO_2_BASEADDR+XGPIO_GIE_OFFSET,XGPIO_GIE_GINTR_ENABLE_MASK);//允许GPIO2中断输出
Xil_Out32(XPAR_AXI_TIMER_0_BASEADDR+XTC_TCSR_OFFSET,Xil_In32(XPAR_AXI_TIMER_0_BASEADDR+XTC_TCSR_OFFSET)&~XTC_CSR_ENABLE_TMR_MASK);//写TCSR,停止计数器
Xil_Out32(XPAR_AXI_TIMER_0_BASEADDR+XTC_TLR_OFFSET,RESET_VALUE);//写TLR,预置计数初值
Xil_Out32(XPAR_AXI_TIMER_0_BASEADDR+XTC_TCSR_OFFSET,Xil_In32(XPAR_AXI_TIMER_0_BASEADDR+XTC_TCSR_OFFSET)|XTC_CSR_LOAD_MASK);//装载计数初值
Xil_Out32(XPAR_AXI_TIMER_0_BASEADDR+XTC_TCSR_OFFSET,(Xil_In32(XPAR_AXI_TIMER_0_BASEADDR+XTC_TCSR_OFFSET)&~XTC_CSR_LOAD_MASK)|XTC_CSR_ENABLE_TMR_MASK|XTC_CSR_AUTO_RELOAD_MASK|XTC_CSR_ENABLE_INT_MASK|XTC_CSR_DOWN_COUNT_MASK);//开始计时运行,自动装载,允许中断,减计数
Xil_Out32(XPAR_AXI_INTC_0_BASEADDR+XIN_IAR_OFFSET,0xffffffff);
Xil_Out32(XPAR_AXI_INTC_0_BASEADDR+XIN_IER_OFFSET,XPAR_AXI_GPIO_2_IP2INTC_IRPT_MASK|XPAR_AXI_GPIO_0_IP2INTC_IRPT_MASK|XPAR_AXI_TIMER_0_INTERRUPT_MASK);//对中断控制器进行中断控制源使能
Xil_Out32(XPAR_AXI_INTC_0_BASEADDR+XIN_MER_OFFSET,XIN_INT_MASTER_ENABLE_MASK|XIN_INT_HARDWARE_ENABLE_MASK);
//微处理器开中断
microblaze_enable_interrupts();
return 0;
}
void My_ISR()
{
int status;
status=Xil_In32(XPAR_AXI_INTC_0_BASEADDR+XIN_ISR_OFFSET);//续敢ISR中断状态寄存器
if((status&XPAR_AXI_TIMER_0_INTERRUPT_MASK)==XPAR_AXI_TIMER_0_INTERRUPT_MASK)
Seg_TimerCounterHandler();//定时器中断服务程序
else if((status&XPAR_AXI_GPIO_2_IP2INTC_IRPT_MASK)==XPAR_AXI_GPIO_2_IP2INTC_IRPT_MASK)
{
BtnHandler();//按键中断服务程序
SwitchHandler();
}
else if((status&XPAR_AXI_GPIO_0_IP2INTC_IRPT_MASK)==XPAR_AXI_GPIO_0_IP2INTC_IRPT_MASK)
SwitchHandler();
Xil_Out32(XPAR_AXI_INTC_0_BASEADDR+XIN_IAR_OFFSET,status);//写IAR中断响应寄存器
}
void Seg_TimerCounterHandler()
{
Xil_Out32(XPAR_AXI_GPIO_1_BASEADDR+XGPIO_DATA_OFFSET,poscode[j+(8-k)]);
Xil_Out32(XPAR_AXI_GPIO_1_BASEADDR+XGPIO_DATA2_OFFSET,segcode[j]);
j++;
if(j>=k)
{
j=0;
}
Xil_Out32(XPAR_AXI_TIMER_0_BASEADDR+XTC_TCSR_OFFSET,Xil_In32(XPAR_AXI_TIMER_0_BASEADDR+XTC_TCSR_OFFSET));//满总中断
}
void BtnHandler()
{
int btncode;
btncode=Xil_In32(XPAR_AXI_GPIO_2_BASEADDR+XGPIO_DATA_OFFSET);
xil_printf("The pushed button's code is 0x%x\n",btncode);
if(btncode==0x1)
{
k=8;
}
else if(btncode==0x2)
{
k=4;
}
else if(btncode==0x10)
{
k=5;
}
Xil_Out32(XPAR_AXI_GPIO_2_BASEADDR+XGPIO_ISR_OFFSET,Xil_In32(XPAR_AXI_GPIO_2_BASEADDR+XGPIO_ISR_OFFSET));
}
void SwitchHandler()
{
xil_printf("switch");
unsigned short key=Xil_In16(XPAR_AXI_GPIO_0_BASEADDR+XGPIO_DATA_OFFSET);
if(k==8)
{
for(int digit_index=0; digit_index<8; digit_index++)
{
segcode[7-digit_index]=segtable[(key>>(digit_index))&0x1];
}
}
else if(k==4)
{
for(int digit_index=0; digit_index<4; digit_index++)
{
segcode[3-digit_index]=segtable[(key>>(4*digit_index))&0xf];
}
}
else if(k==5)
{
for(int digit_index=0; digit_index<5; digit_index++)
{
segcode[4-digit_index]=segtable[key%10];
key = key/10;
}
}
Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR+XGPIO_ISR_OFFSET,Xil_In32(XPAR_AXI_GPIO_0_BASEADDR+XGPIO_ISR_OFFSET));
}
说明:使用软件为Vivado 2018.3,使用的开发板为Nexys4 DDR