ARM裸机开发 您所在的位置:网站首页 arm汇编程序设计实验 ARM裸机开发

ARM裸机开发

2024-05-28 16:25| 来源: 网络整理| 查看: 265

写在前面

 本报告因为期末将至,后续还需要完成一次课程设计,故本次实验较为简单,完成的时间也非常匆忙,故文章内容较为单薄,也可能有着更多疏忽之处,还望大家海涵。

1. 项目任务

 1) 利用S3C2440手册,掌握嵌入式系统三个时钟关系(FCLK、HCLK、PCLK)和异步通信协议,分析解读异步通信寄存器的初始化;  2) 利用ARM机自带键盘,用串行方式实现ARM机的数据传送程序;  3) 实现两台ARM机之间异步通信。具体内容:实现带启动的三键控制控制对方三灯程序。即启动键有效时,一个键点亮另一台ARM机的三个灯,一个键关闭另一台ARM机的三个灯,一个键控制另一台ARM机的三灯跑马。启动键无效时,三键不起控制作用(单键用查询);  4) 编写交叉编译文件Makefile;

2. 项目方案设计

 本实验为ARM裸机开发——双机异步串行通信,主要目的是通过ARM裸机开发实现双机异步串行通信。本项目的实现框图如图2.1所示。 在这里插入图片描述

图2.1 实验步骤方案设计图  本报告以串行通信、嵌入式时钟原理、程序设计三部分阐述。 3. 串行通信原理

 本实验将以经典的UART通信,即全双工异步串行通信协议,进行通信协议的学习与运用,并且通过UART通信进一步理解嵌入式系统裸机开发原理。

3.1. 异步串行通信原理(UART)

 以最为经典的AT89C52单片机的异步串行通信为例,UART通信为一种全双工、异步、串行通信协议。全双工,意味着双方可以同时进行收发,即“我”可以接收到“你”的数据,同样可以把数据发送给“你”,也即一对一,无法多方通信;异步,实际是数据收发与时钟不同步的概念,即接收方不确定数据在何时到来;串行,数据需要依次通过数据线进行发送,如同绳串一样,发送完当前数据后,才可以发送下一个数据。  在清晰UART通信协议含义后,如何具体实现UART通信,就需要清晰应用概念。如图3.1所示,介绍部分UART通信应用概念。 在这里插入图片描述

图3.1 UART数据通信协议

 1) 空闲位。当UART双方无数据收发时,双方引脚均保持高电平,即数据为‘1‘,处于空闲状态。  2) 起始位。当UART开始收发数据时,发送方发送低电平,即逻辑‘0’,表示数据通信开始。因为空闲位为高电平,所以起始位需要区别于空闲位。  3) 数据位。数据位可以设置为5至8位,对于有线通信而言,通常采用8位数据位一个字节方便读取存储;对于无线红外通信模式,使用较少的数据位可以减少丢包率。  4) 奇偶校验位。奇偶校验是简单实用的数据传输校验方式,通过计数数据传输中逻辑‘1’的数量为奇数还是偶数,进行简单的数据校验。由于UART通信通常适用于传输速度低,数据量较少的情况下,利用简单的奇偶校验即可一定程度上保证数据准确。  5) 停止位。当数据发送完成时,发送方发送高电平为停止位,以表示数据收发结束,可以设置1至2位停止位。  由于UART通信无时钟线,那如何保证数据通信的准确性,换句话说,当第一位数据结束时,何时为下一位数据位,双方如何保证当前数据位为第几位数据位。打个比方,两人通话时,如果一方的语速超过另一方大脑接收语言的处理速度,那么就无法正常通话,在这里的语速,就是数据收发的速率,即波特率。  实际上,波特率,即为每位数据位的传输时间的倒数,换句话说波特率的倒数即为每隔多少时间需要数据采样一次,如此才能保证在无时钟线的情况下,保证数据双方进行数据通信的准确性。由于串口通信协议的芯片电气传输特性限制的最大传输速率为115200bps,所以通常采用的波特率为115200的分频数,如9600、19200bps。例如本次实验波特率采用了19200bps,利用示波器测量串口通信数据,如图3.2所示。 在这里插入图片描述

图3.2 串口通信波特率测量  根据波特率计算公式

b a u d r a t e = 1 b i t p e r i o d = 1 52.10 u s = 19194 b p s ≈ 19200 b p s baud rate= \frac{1}{bit period} = \frac{1}{52.10us} = 19194bps ≈ 19200bps baudrate=bitperiod1​=52.10us1​=19194bps≈19200bps

 根据上述的实验,可见实际波特率的测量与理论波特率误差极小,换句话说在数据传输较慢时,UART通信的丢包率较小。  AT89C52单片机中的UART通信为最为经典的串口通信协议,嵌入式系统在除上述基本概念以外,引入了FIFO存储器、流控控制、状态检测等控制方式。  FIFO存储器,即先进先出、后进后出存储器,为队列存储器,当UART收到数据后,随即将数据压入队列存储器中,直到队列存储器满。FIFO存储器的使用框图如图3.3所示。 在这里插入图片描述

图3.3 FIFO存储器使用框图  当CPU进程占用时,如果不采用FIFO存储器,UART收到数据无法立即存储,会导致当前数据被下一次数据所覆盖,FIFO存储器相当于提供UART数据缓冲区,当CPU空闲时,读取UART缓冲区数据,以保证数据的完整性。 3.2. 寄存器配置方式

 与实验二中存储器外部设备寄存器初始化相类似,UART配置流程如图3.4所示。 在这里插入图片描述

图3.4 UART配置流程  以本次实验为例,我们假设UART数据通信协议为8位数据位,1位起始位,1位停止位,无奇偶校验位;波特率为19200,无流控,不采用FIFO存储器。  编写UART_Init函数,如图3.5所示,并以此程序详细解读UART寄存器配置方式。

在这里插入图片描述

图3.5 串口通信初始化函数

 根据图3.4 UART配置流程。  1) ULCON:UART线路控制寄存器,主要控制UART数据发送方式,即数据位长度与停止位个数,以及奇偶校验位选择。如ULCON=0x03;即8数据位,1起始位,1停止位,无奇偶校验位模式。  2) UCON:UART控制寄存器,控制UART时钟源设置,以及时钟源分频设置,以及UART收发采用方式设置,由于中文数据手册对于该寄存器说明有所缺失,在此补充寄存器[3:0]位说明,如图3.6。如UCON=0x05;即均采用中断或者查询模式,时钟源为PCLK。  3) UFCON:UART FIFO控制寄存器,控制FIFO存储器使用的相关配置,本实验未使用FIFO,为此UFCON=0x00。  4) UMCON:UART Modem寄存器,即流控控制寄存器,本实验不使用流控方式,为此UMCON=0x00。  5) UBRDIV:波特率寄存器,通过该寄存器具体设置波特率分频值,本实验中设置波特率为19200bps,根据公式UBRDIV=(int)(UART 时钟/(baud rate×16))-1  综上,五个UART寄存器即可实现UART通信基本配置,但是由于在实际运行中,无法得知数据会在何时到来,所以通常对于接收数据采用接收中断的方式,而发送数据采用轮询的方式,为此需要配置接收中断的寄存器,以实验二中断配置为例,本实验不赘述。 同时,UART通信空闲位为1,所以需要配置UART管脚上拉,同时配置管脚准双向输入输出模式。

4. 嵌入式时钟原理

 UART通信中引入了时钟的设置,借以此引入嵌入式时钟树,并尝试与单片机时钟比较,探讨嵌入式时钟树的作用与意义,将以嵌入式时钟树原理、时钟树配置方式两方面阐述。

4.1. 嵌入式时钟树原理

 与单片机有所不同,嵌入式系统的高性能往往带来了外部设备众多,系统更为复杂,采用单一的时钟总线的方法,无法满足所有外部设备的时钟要求。对于51单片机而言,其运用场合往往是低速、简单控制、设备稳定的场合,采用低速时钟线,可以降低功耗。  为满足低速信号、高速信号、CPU等设备的时钟需求,S3C2440将主要的时钟线为三种,即提供给CPU的FCLK,提供AHB总线外设的HCLK以及提供给APB总线外设的PCLK,其中AHB总线为高级高性能外设总线,APB为精简低功耗外设总线,以此来区分三种时钟线。打个比方,CPU为大脑,需要提供最为快速的信号处理与反应,所以需要提供最为快速的FCLK时钟线;AHB总线外设为神经系统,需要尽可能快地传递感受信息,需要高速HCLK;APB总线为执行器,无法做到与神经反应相同的反应速度,所以利用慢速PCLK时钟线即可。嵌入式整体的时钟处理框图如图4.1所示。

在这里插入图片描述

图4.1 时钟系统框图  在大致理清三者时钟线的关系后,如图4.1具体来看时钟系统的产生方式。FCLK、HCLK、PCLK三时钟总线均可以通过同一个时钟源进行产生,时钟源的选择可以为外部晶振或者芯片内部的时钟振荡电路产生,通常采用外部晶振的方式提供时钟源,外部晶振产生的时钟信号更为稳定。UCLK主要为提供USB模块时钟,不是本嵌入式系统的主要时钟线,在此不详细分析,下面主要分析时钟FCLK、HCLK、PCLK产生与分频设置,绘制了时钟信号产生流程图如图4.2所示。

在这里插入图片描述

图4.2 时钟线产生

 1) 时钟源产生时钟信号作为 F i n F_{in} Fin​,提供给PLL锁相环。  2) PLL锁相环,得到 F i n F_{in} Fin​后,将 F i n F_{in} Fin​信号通过分频或倍频的方式,同时将信号相位同步后,得到时钟参考信号MPLL,具体MPLL频率计算公式为 M P L L = 2 × m × F i n p × 2 S MPLL=\frac{2×m×F_{in}}{p×2^S} MPLL=p×2S2×m×Fin​​

 3) Power Management,得到MPLL参考时钟信号后,通过设置分频器和电源管理模块使能,得到FCLK、HCLK、PCLK三时钟信号。  以上便是时钟信号的具体产生过程,在下一部分具体分析时钟信号配置方法。

4.2. 时钟信号配置方法

 时钟线具体配置,实际即确定三时钟线的时钟频率,以本实验的时钟设定为具体演示。令FCLK=200MHz, HCLK=100MHz, PCLK=50MHz根据图4.2时钟产生方法,编写了clock_init函数,如图4.3所示

在这里插入图片描述

图4.3 clock_init函数 5. 嵌入式系统程序设计

 本部分主要演示代码框架和具体代码内容,程序设计将分为代码实现、代码调试问题两部分阐述。

5.1. 代码实现

 本实验整体框架与实验二类似,均采用了中断得到系统状态标志位,主循环根据状态标志位进行不同模式的程序执行,启动引导代码与实验二一致,故本程序设计不涉及启动引导代码,流程如图5.1所示

在这里插入图片描述

图5.1 程序设计流程图

 本次实验与实验二,整体思路与框架一致,实验较为简单,暂无太多代码改变之处,主要放出与UART相关代码,如下

/*********************************************** * void UART_Init(void) * 函数功能:UART初始化函数,使用UART1,TXD-GPH4, RXD-GPH5 * 协议:数据位8位,1位起始位,1位停止位,无奇偶校验位 * 波特率19200 * 无流控 * 暂时不带FIFO * 无错误检查 * 暂时固定式初始化,后续借鉴HAL库中的UART初始化方式 * ***********************************************/ void UART_Init(void) { // UART Line Control 线路控制寄存器,由于控制通信数据协议 ULCON1 = 0X03; // 8数据位,1起始位,1停止位,无奇偶校验位 // UART Control 控制寄存器,控制时钟,中断等模式 UCON1 = 0x05; // 发送与接收均采用中断或者查询模式,时钟为PCLK // 中文数据手册中缺少了部分说明 其中UCON[3:0]控制UART的传输模式,如屏蔽,中断查询模式 // UART FIFO控制寄存器,FIFO为队列存储器,先进先出,后进后出 UFCON1 = 0x00; // 不使用FIFO // Modem 控制器,控制流控 UMCON1 = 0x00; // 不使用流控 // 波特率分频寄存器 UBRDIV1 = UART_BRD; // 波特率为19200 GPHCON |= 0x000a00; // GPH4,GPH5用作TXD1,RXD1 GPHUP &= ~(0x030); // GPH4,GPH5内部上拉 // 设置接收中断 // 配置中断模式,均为普通中断IRQ INTMOD &= ~(BIT_UART1); // BIT_xx 对应中断源位 // 优先级采用复位值 INTSUBMSK &= ~(BIT_SUB_RXD1); // 接收中断使能 INTMSK &= ~(BIT_UART1); } /**************** * int fputc(int c, FILE *f) * 重定向printf函数,但是对于ARM裸机开发,调用标准库的过程暂未解决 * **************/ // int fputc(int c, FILE *f) // { // while(!(UTRSTAT1 & TXDREADY)); // UTXH1 = c; // return c; // } /***************************************** * void void UART_SendData(unsigned char c) * UART单字节发送函数 * *************************************/ void UART_SendData(unsigned char c) { /* 等待,直到发送缓冲区中的数据已经全部发送出去 */ while (!(UTRSTAT1 & TXDREADY)); /* 向UTXH1寄存器中写入数据,UART即自动将它发送出去 */ UTXH1 = c; } /* * 接收字符 */ unsigned char UART_GetData(void) { /* 等待,直到接收缓冲区中的有数据 */ while (!(UTRSTAT1 & RXDREADY)); /* 直接读取URXH1寄存器,即可获得接收到的数据 */ return URXH1; } /***************************************** * void UART1_IRQHandle(void) * 暂时仅为接收中断函数,对于发送通常采用轮询模式 * *************************************/ void UART1_IRQHandle(void) { SUBSRCPND = (1


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有