作者:毛茏玮 / Saint
掘金:https://juejin.im/user/5aa1f89b6fb9a028bb18966a
微博:https://weibo.com/5458277467/profile?topnav=1&wvr=6&is_all=1
GitHub:github.com/saint-000
CSDN: https://me.csdn.net/qq_40531974
一、实验目的
1.掌握ARM的GPIO,UART接口工作原理。
2.学习编程实现GPIO接口的控制及ARM和PC机的UART通信。
3.掌握ARM裸机下C语言编程方法。
二、实验内容
1.学习串行通信原理,了解串行通信控制寄存器。
2.实现I/O接口编程。
三、实验步骤
1.数码管实验
1.双击打开对应工程文件夹下的vivado project file
2.在File菜单下选择Export,点击包括比特流,点击OK
3.在File菜单下选择luanch SDK,打开SDK软件
4.新建工程并命名,类型选择Empty Application
5.在新建的工程中添加源文件,新建Source File
6.为文件命名,注意要跟上文件类型.c,点击Finish
7.补全seg_test.c文件中缺失的代码,添加至源文件中:需完成的功能:
使用开关控制右四位数码管显示数字0~9,当值大于9时,数码管无显示
其中开关从右至左为低位至高位,开关开状态为1,关状态为0,开关组成的2进制值对 应数码管上显示的十进制数值
8.点击保存,软件自动编译程序
9.用USB数据线将开发板2处接口与电脑主机连接,打开板子电源开关7,开发板1处拨码开关全部打到”on”
10.在vivado中点击左下角Open Hardware Manager,选择open target, 再选择Auto Connection
11.点击Program device,在弹出的窗口中找到工程的比特流,比特流文件在工程中的路径为:project_name/project_name.runs/impl_1/system_wrapper.bit,如下图,点击Program下载比特流到板子
12.运行程序
13.拨动开关,观察数码管上的显示
14.可使用debug调试程序,具体参见实验二
2.UART串口实验
1.双击打开对应工程文件夹下的vivado project file
2.在File菜单下选择Export,点击包括比特流,点击OK
3.在File菜单下选择luanch SDK,打开SDK软件
4.新建工程并命名,类型选择Empty Application
5.在新建的工程中添加源文件,新建Source File
6.为文件命名,注意要跟上文件类型.c,点击Finish
7.补全common_uart.c文件中缺失的代码,添加至源文件中,需完成的功能:
通过PL上的UART串口发送单个字符,接收后向串口回传该字符,若收到的字符为“x”,则退出程序
8.点击保存,软件会自动编译程序
9.用USB数据线将开发板2处UART接口与电脑主机连接,将5上方的USB口用双头USB线连接至主机,打开板子电源开关7
10.在vivado中点击左下角Open Hardware Manager,选择open target, 再选择Auto Connection
11.点击Program device,在弹出的窗口中找到工程的比特流,比特流文件在工程中的路径为:project_name/project_name.runs/impl_1/system_wrapper.bit,如下图,点击Program下载比特流到板子
12.计算机→管理,在设备管理器→端口里查看Silicon Labs CP210x USB to UART Bridge对应的端口号
13.打开串口调试助手,将串口设置为该端口号,将波特率设为9600,其余配置不改变,然后打开串口
14.运行程序
15.在串口助手里,输入字符,点击TX发送,在左上方的框里看是否有接受到正确的字符
四、实验结果
实验1.在搭建好的工程文件下编写实验程序,实现对数码管的位选和段选的控制。实验截图如下:
实验代码如下:
#include"xparameters.h"
#include"xgpio.h"
#include"xil_cache.h"
//设备ID
#define GPIO_SEG_W_DEVICE_ID 1
#define GPIO_SW_DEVICE_ID 2
#define GPIO_SEG_D_DEVICE_ID 0
//通道号
#define SEG_CHANNEL 1
//指向设备的指针
XGpio GpioOutput0; //位选对应寄存器
XGpio GpioOutput1; //段选对应寄存器
XGpio GpioInput;//按键对应寄存器
u32 flag=0;
u32 DataRead;
int Gpio_w_seg(u16 Deviceid)
{
int w;
int status;
/*请补全代码,给w赋值*/
w=15;
status=XGpio_Initialize(&GpioOutput0,Deviceid);
if(status !=XST_SUCCESS)
{
return XST_FAILURE;
}
XGpio_SetDataDirection(&GpioOutput0,SEG_CHANNEL,0x0);
XGpio_DiscreteWrite(&GpioOutput0,SEG_CHANNEL,w);
return XST_SUCCESS;
}
int Gpio_d_seg(u16 Deviceid,u32 data)
{
u32 a;
int status;
status=XGpio_Initialize(&GpioOutput1,Deviceid);
if(status !=XST_SUCCESS)
{
return XST_FAILURE;
}
/*设置GPIO为输出*/
XGpio_SetDataDirection(&GpioOutput1,SEG_CHANNEL,0x0);
switch(data)
{
case 0 :a=0x3f;
break;
/*补全余下代码,定义data为1~9时对应的数码管值*/
case 1 :a=0x06;
break;
case 2 :a=0x5b;
break;
case 3 :a=0x4f;
break;
case 4 :a=0x66;
break;
case 5 :a=0x6d;
break;
case 6 :a=0x7d;
break;
case 7 :a=0x07;
break;
case 8 :a=0x7f;
break;
case 9 :a=0x6f;
break;
}
/*向数码管寄存器中写入值*/
XGpio_DiscreteWrite(&GpioOutput1,SEG_CHANNEL,a);
return XST_SUCCESS;
}
u32 Gpio_sw(u16 Deviceid,u32 *DataRead)
{
int Status;
Status = XGpio_Initialize(&GpioInput, Deviceid);
if (Status != XST_SUCCESS)
{
return XST_FAILURE;
}
/*补全代码,读取并返回按键的值*/
return XGpio_DiscreteRead(&GpioInput, SEG_CHANNEL);
}
void main()
{
while(1)
{
flag =Gpio_sw(GPIO_SW_DEVICE_ID,&DataRead);
Gpio_w_seg(GPIO_SEG_W_DEVICE_ID);
if(flag < 10)
{
Gpio_d_seg(GPIO_SEG_D_DEVICE_ID,flag);
}
else
{
/*补全代码,使数码管不显示*/
XGpio_Initialize(&GpioOutput0,GPIO_SEG_D_DEVICE_ID);
XGpio_SetDataDirection(&GpioOutput1,SEG_CHANNEL,0x0);
XGpio_DiscreteWrite(&GpioOutput1,SEG_CHANNEL,0x0000);
}
}
}
实验2. ARM C语言实现串口通信实验。实验代码如下:
#include "xparameters.h"
#include "xil_printf.h"
#include "sleep.h"
#include
#include "xil_io.h"
#define uart_bas_addr 0x42c00000
#define uart_rxd_addr 0x42c00000//接收数据输入地址
#define uart_txd_addr 0x42c00004//发送数据输出地址
#define uart_stat_addr 0x42c00008 // 串口状态寄存器
#define uart_ctrl_addr 0x42c0000c
int main()
{
while(1)
{ /*补全代码,接收字符并回传,当接收到字符x时退出程序*/
static int a;
if((Xil_In8(uart_stst_addr))&0x01==1)//判断串口状态寄存器的最低位是否为1
{
a=Xil_In8(uart_txd_addr, a);//若为1,接收串口数据,并赋给一个变量
if(a=='x')//将接收到的数据回传
{
break;//判断接收到的数据是否位‘x’,若是,跳出while循环
}
}
}
return 0;
}
实验截图如下:
五、实验总结
1.知道八段数码管由“位选”和“段选”两块电路驱动以及引脚约束条件。
2.理解了接口函数的用法。
3.用串口助手修改波特率,连接开发板的UART进行匹配打印返回值
实验心得:
(1)串口通信的实验明显要比之前的实验要难了,代码的数量明显变多了 。头文件里有很多的代码,比之前的实验的代码要多的多。
但是只要认真的去看代码,使用编译器自带的查找功能找到关键的函数,很容就看懂代码本身的意思。
(2)串口通信的概念,即串口按位(bit)发送和接收字节。通过这次实验,我掌握了串口的使用方法,串口初始化,发送数据和接收数据,为以后的实验奠定了基础。通过有关书籍,我了解到嵌入式系统中串口是一个重要的资源,常用来做输入输出设备。
(3)UART(通用异步收发器)结构包括波特率发生器,发送器,接收器以及控制单元;
有同时代表收发缓冲区状态的只读UTRSTAT寄存器,和其他收发数据,设计相应收发模式查询方式的寄存器;
实验过程就是对发送数据格式,端口,寄存器等初始化,接收数据(接收缓冲区接收到数据),发送数据(发送缓冲区为空)的处理。
六、实验思考题
(1)查看相关寄存器,思考怎么配置UART时钟信号?
改变ulcon的值可以配置UART配置寄存器。我们实验室用的芯片xc7z020clg484-1,所以我们查看xc7z020的数据手册,查看CLOCK&POWER MANAGEMENT和UART模块相关配置时钟信号的寄存器来确定时钟信号。
(2) 要实现控制数码管闪烁的功能,有什么办法可以完成?
可以向命令寄存器写入闪烁控制命令,也可以通过向命令寄存器中写入“下载数据并译码(Download)"命令来完成,因为该命令的底八位的D6位可以控制数码管的闪烁。