题目
基于AXI GPIO IP核设计16位独立开关、16位独立LED以及8位共阳极型七段数码管接口电路,要求仅采用一个GPIO IP核,其中16位独立开关(低16位)、16位LED(高16位)共用通道GPIO,8位七段数码管的位选(高8位)和段选信号(低8位)共用通道GPIO2。若该GPIO IP核接口基地址为0x40000000,试基于Xilinx Standalone BSP端口读写函数编写控制程序分别实现以下功能:
(1) 实时获取16位开关的状态,并及时反映在16位LED对应位上,同时将16位开关对应的4位十六进制数字从高到低依次显示在8位七段数码管的位5~位8上,其余数码管灭。
(2) 实时获取16位开关的状态,并将16位开关分为高8位、低8位,分别当作两个8位符号数,将它们的和、差二进制数分别输出到16位LED的高8位、低8位,同时将和、差对应的2位十六进制数字分别输出到8位七段数码管的位3~位4、位7~位8上,其余数码管灭。
(3) 实时获取16位开关的状态,并将16位开关分为高13位(SW15~3)、低3位(SW2~0)两部分,要求将SW15~3 13位无符号二进制数(D12~0)表示的十进制数显示在8位七段数码管上,且最高位从SW2~0(1≤SW2~0≤5)所指示位置开始显示,无数据数码管灭。即若SW15~0=0xfff9,那么8位七段数码管显示结果如题图 7‑9所示。
题图 7‑9 SW15~0=0xfff9时8位七段数码管显示结果
以上3题分为三个独立的应用程序,请同学们提交三个C语言程序段,对应提交三个应用运行时开发板的三张实际效果照片。
做得我醉生梦死还因此鸽了桌游,不留个档对不起我的周末。)
第一题
/*
* led.c
*
* Created on: 2024年4月28日
* Author: wxt
*/
#include "xil_io.h"
#include <stdio.h>
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};//位码表
int main()
{
//Xil_In8(0x40000000);
//GPIO1
Xil_Out8(0x40010004,0x0);
Xil_Out8(0x4001000c,0x0);
//GPIO2
Xil_Out16(0x40000004,0xffff);
Xil_Out16(0x4000000c,0x0);
while(1)
{
for(int i=0;i<4;i++)
{
short Key = Xil_In16(0x40000000);//读入开关状态
Xil_Out16(0x40000008,Key);//更新led灯
//将开关代表的数字更新到显示缓冲区
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++);//延时控制
}
}
return 0;
}
结果:
开关状态为:1100 1110 0011 1010
结果正确
第二题
/*
* led.c
*
* Created on: 2024年4月28日
* Author: wxt
*/
#include "xil_io.h"
#include <stdio.h>
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[8] = {0x7f, 0xbf, 0xdf, 0xef, 0xf7,0xfb,0xfd,0xfe};//位码表
short binary_to_decimal(short binary) {
int decimal = 0;
int bit = 0;
int mask = 1; // 用于提取二进制数的每一位
// 从最低位到最高位遍历二进制数
while (binary) {
// 通过位与操作提取当前位的值
int bit_value = binary & mask;
// 将当前位的值加到十进制数上
decimal += bit_value * (1 << bit);
// 移动到下一位
bit++;
// 移除最低位
binary >>= 1;
}
return decimal;
}
short decimal_to_binary(int n)
{
short binaryNumber = 0;
int remainder, i = 1;
while (n!=0)
{
remainder = n%2;
n /= 2;
binaryNumber += remainder*i;
i *= 10;
}
return binaryNumber;
}
int main()
{
//Xil_In8(0x40000000);
//GPIO1
Xil_Out8(0x40010004,0x0);
Xil_Out8(0x4001000c,0x0);
//GPIO2
Xil_Out16(0x40000004,0xffff);
Xil_Out16(0x4000000c,0x0);
while(1)
{
for(int i=0;i<4;i++)
{
short Key = Xil_In16(0x40000000);//读入开关状态
short high8 = (Key>>8) & 0xff;//取出高八位和低八位
short low8 = Key & 0xff;
short sym_high = (high8>>7)& 0x1;//取出符号位
short sym_low = (low8>>7)& 0x1;
short high_number = binary_to_decimal(high8 & 0x7f);//取出数值位
short low_number = binary_to_decimal(low8 & 0x7f);
short sym_minus ;
short minus_number ;
short sym_sum ;
short sum_number ;
if(sym_high == sym_low)
{
minus_number = (high_number > low_number)?(high_number - low_number):(low_number - high_number);
sum_number = high_number + low_number;
sym_minus = (high_number >= low_number)?0:1;
sym_sum = sym_high;
}else
{
minus_number = high_number + low_number;
sym_minus = sym_high;
sum_number = (high_number > low_number)?(high_number - low_number):(low_number - high_number);
sym_sum = (high_number >= low_number)?sym_high:sym_low;
}
short led_result = (sym_sum<<15) | (sum_number<<8) | (sym_minus <<7) | minus_number;
Xil_Out16(0x40000008,led_result);//更新led灯
short result = (sum_number<<8) | minus_number;
//将和与差更新到显示缓冲区
for(int digit_index=0;digit_index<4;digit_index++)
segcode[3-digit_index] = segtable[(result>>(4*digit_index)) & 0xf];
Xil_Out8(0x40010000, poscode[2]);//第3位
Xil_Out8(0x40010008, segcode[0]);
for(int j = 0; j<10000;j++);//延时控制
Xil_Out8(0x40010000, poscode[3]);//第4位
Xil_Out8(0x40010008, segcode[1]);
for(int j = 0; j<10000;j++);//延时控制
Xil_Out8(0x40010000, poscode[6]);//第7位
Xil_Out8(0x40010008, segcode[2]);
for(int j = 0; j<10000;j++);//延时控制
Xil_Out8(0x40010000, poscode[7]);//第8位
Xil_Out8(0x40010008, segcode[3]);
for(int j = 0; j<10000;j++);//延时控制
}
}
return 0;
}
结果:
输入1 000 0100 _ 1 001 0100
即 (-12)和 8
数码管3、4位表示和,7、8位表示差
左边8个led表示和(8位有符号位二进制数),右边8位led表示差
-12+8 = -4
-12-8=-20
结果正确
第三题
/*
* led.c
*
* Created on: 2024年4月28日
* Author: wxt
*/
#include "xil_io.h"
#include <stdio.h>
char segtable[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //段码表
char segcode[4] = {0xc0, 0xc0, 0xc0, 0xc0};//显示缓冲区
short poscode[8] = {0x7f, 0xbf, 0xdf, 0xef, 0xf7,0xfb,0xfd,0xfe};//位码表
int binary_to_decimal(short binary) {
int decimal = 0;
int bit = 0;
int mask = 1; // 用于提取二进制数的每一位
// 从最低位到最高位遍历二进制数
while (binary) {
// 通过位与操作提取当前位的值
int bit_value = binary & mask;
// 将当前位的值加到十进制数上
decimal += bit_value * (1 << bit);
// 移动到下一位
bit++;
// 移除最低位
binary >>= 1;
}
return decimal;
}
int main()
{
//GPIO1
Xil_Out8(0x40010004,0x0);
Xil_Out8(0x4001000c,0x0);
//GPIO2
Xil_Out16(0x40000004,0xffff);
Xil_Out16(0x4000000c,0x0);
while(1)
{
for(int i=0;i<4;i++)
{
short Key = Xil_In16(0x40000000);//读入开关状态
Xil_Out16(0x40000008,Key);//更新led灯
short high8 = (Key>>3) & 0x1fff;
short low8 = Key & 0x7;
int number = binary_to_decimal(high8);
//更新到显示缓冲区
int digit_index;
for(digit_index=0;digit_index<4 && number != 0;digit_index++)
{
segcode[3 - digit_index] = segtable[number%10];
number = number / 10;
}
for(int pos = 0; pos < 4 && pos <= digit_index; pos ++)
{
Xil_Out8(0x40010000, poscode[pos + low8 - 1]);//第3位
Xil_Out8(0x40010008, segcode[pos]);
for(int j = 0; j<10000;j++);//延时控制
}
}
}
return 0;
}
结果:
输入0xfff9
结果正确