程序控制方式GPIO应用-华中科技大学计算机组成原理作业

题目

基于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

结果正确

  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值