实验一 串口通讯实验
一、 实验目的
1. 掌握ARM的串行口工作原理。
2. 学习编程实现ARM的UART通讯。
3. 掌握S3C2410寄存器配置方法。
二、 实验内容
实现查询方式串口的收发功能。接收来自串口(通过超级终端)的字符并将接收到的字符发送到超级终端。
三、 预备知识
1. 了解ADS集成开发环境的基本功能。
2. 学习串口通讯的基本知识。
3. 熟悉S3C2410串口有关的寄存器。
四、 实验设备
硬件:2410s教学实验箱、ARM920T的JTAG仿真器、串口连接线。 软件:ARM ADS1.2集成开发环境、超级终端通讯程序。
五、 实验步骤
1.以实验一为模板,完成实验的1和2。
2.将接收串口数据的数组cl[1]改为cl[256],用cl[i]==0x0d 回车字符作为一
帧结束的条件。
3.将“Exp4 电机转动控制实验” inc目录下的MotorCtrl.H 和src目录下
的MotorCtrl.C拷到该工程相应目录,将MotorCtrl.C 添加到工程中。
4.在main函数里包含以下头文件 #include “../inc/MotorCtrl.h”。
5.在main函数里包含以下头文件 #include “inc/macro.h“ ,
#define MOTOR_COUNT 12657
6.在Main函数里执行init_MotorPort();
1
7.直流电机调试的函数是 SetPWM((setspeed
-512)*MOTOR_COUNT/1024),setspeed是速度指令,取值范围0~1023.
8.程序代码如下:
/***************************************************************************\
Copyright (c) 2004-2007 threewater@up-tech.com, All rights reserved. by threewter 2004.5.12
\***************************************************************************/
/***************************************************************************\
#说明: C main 函数,ucos-ii初始化等定义
---------------------------------- Bug --------------------------------------
---------------------------------- TODO list --------------------------------------
----------------------------------修正--------------------------------------
2004-5-12 创建
\***************************************************************************/
//#include"../ucos-ii/includes.h" /* uC/OS interface */
//#include "../ucos-ii/add/osaddition.h"
//#include "../inc/drivers.h"
//#include "../inc/sys/lib.h"
//#include "../src/gui/gui.h"
#include "../inc/MotorCtrl.h"
#include "../inc/macro.h"
#define MOTOR_COUNT 12657
#define U8 unsigned char
#include <string.h>
#include <stdio.h>
#define TRUE 1
#define FALSE 0
//#pragma import(__use_no_semihosting_swi) // ensure no functions that use semihosting
#define rUTRSTAT0 (*(volatile unsigned *)0x50000010)
#define rUTRSTAT1 (*(volatile unsigned *)0x50004010)
#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)
#define WrUTXH1(ch) (*(volatile unsigned char *)0x50004020)=(unsigned 2
char)(ch)
#define RdURXH0() (*(volatile unsigned char *)0x50000024)
#define RdURXH1() (*(volatile unsigned char *)0x50004024)
//void Uart_SendByten(int Uartnum, U8 data);
void Uart_SendByten(int,U8*);
char Uart_Getchn(char* Revdata, int Uartnum, int timeout);
char String2BCD(char *Revdata, char *BCDcode);
char SetMotorSpeed(char *BCDcode);
void ARMTargetInit(void);
void hudelay(int time);
void printBCD(char *BCDcode)
{
for(int i=0;i<4;i++)
{
while(!(rUTRSTAT0 & 0x4)); //Wait until THR is empty.
hudelay(10);
WrUTXH0(BCDcode[i]+'0');
}
}
int main(void)
{ //int ndev;
char c1[256];
char Bcd[4];
char err;
ARMTargetInit(); // do target (uHAL based ARM system) initialisation //
init_MotorPort(); // 执行电机初始化
while(1)
{
//Uart_SendByten(0,0xa);//换行
//Uart_SendByten(0,0xd);//回车
err=Uart_Getchn(c1,0,0); //从串口采集数据
//Uart_SendByten(0,"hello\n");
if(String2BCD(c1, Bcd))
if(SetMotorSpeed(Bcd))
{
Uart_SendByten(0,"MotorSpeed = ");
printBCD(Bcd);
Uart_SendByten(0,"\r\n");
}
else
{
Uart_SendByten(0,"Too Large.");
Uart_SendByten(0,c1);
Uart_SendByten(0,"\r\n");
}
3
else
{
Uart_SendByten(0,"Invalid.\r\n"); Uart_SendByten(0,c1);
Uart_SendByten(0,"\r\n");
}
//if (err==TRUE)
// Uart_SendByten(0,c1[0]); //显示采集的数据 }
}
char String2BCD(char *Revdata, char *BCDcode)
{
int i;
for(i = 0; i < 4; i++)
BCDcode[i] = 0;
for(i = 0; i < 4; i++)
{
if(Revdata[i] >= '0' && Revdata[i] <= '9')
{
for(int j = 0; j < 4 - 1; j++)
BCDcode[j] = BCDcode[j + 1];
BCDcode[3] = Revdata[i] - '0';
}
else if(i && Revdata[i] == 0X0D)
return TRUE;
else
return FALSE;
}
if(Revdata[4] == 0X0D)
return TRUE;
else
return FALSE;
}
char SetMotorSpeed(char *BCDcode)
{
int speed = 0;
for(int i = 0; i < 4; i++)
speed = speed * 10 + BCDcode[i];
if(speed >= 1024)
return FALSE;
SetPWM((speed - 512) * MOTOR_COUNT / 1024); return TRUE;
}
void Uart_SendByten(int Uartnum, U8 *data)//ok eric rong {
int i = 0;
4
if(Uartnum==0)
{
while(data[i]!=0 && i<512)
{
while(!(rUTRSTAT0 & 0x4)); //Wait until THR is empty.
hudelay(10);
WrUTXH0(data[i]);
i++;
}
}
else
{
while(!(rUTRSTAT1 & 0x4)); //Wait until THR is empty.
hudelay(10);
WrUTXH1(data);
}
}
char Uart_Getchn(char* Revdata, int Uartnum, int timeout)
{
int dataRecieved=0;
if(Uartnum==0){
while(1)
{
while(!(rUTRSTAT0 & 0x1)); //Receive data read
Revdata[dataRecieved]=RdURXH0();
if(Revdata[dataRecieved]==0X0D)
{
Revdata[dataRecieved + 1] = 0;
return TRUE;
}
if(++dataRecieved>=255)
return FALSE;
}
}
else{
while(!(rUTRSTAT1 & 0x1));//Receive data read
*Revdata=RdURXH1();
return TRUE;
}
}
六、 实验思考
1. 232串行通讯的数据格式是什么?
RS-232属于“异步传输”,在传送数据时,并不需要另外使用一条传输线来传送同步信号,不过必须在每一组数据的前后都加上同步信号,把同步信号与数 5
据混和之后,使用同一条传输线来传输。从低位到高位的一帧数据格式为:
---------------------------------------------------------------------------------------
起始位(Start)+数据位(Data)+奇偶校验位(Parity)+停止位(Stop)
----------------------------------------------------------------------------------------
其中起始位固定为一个比特,停止位则可以是1、1.5或者是2比特(传送与接受一致),数据位可以设置为7、8或者9,奇偶校验位可以设置为无(N)、奇(O)或者偶(E),奇偶校验位可以使用数据中的比特。
2. 串行通讯最少需要几根线,分别如何连接?
以9芯D型插头为例,至少需要3根数据线:串口的2脚(发送数据TXD)与另一串口的3脚(接收数据RXD)连接,同时两串口的5脚(信号地)连接在一起。
3. ARM的串行口有几个,相应的寄存器是什么?
2410/2330自带3个UART端口通道,每个通道都可以工作于中断或者DMA模式,且都有16字节的FIFO用于数据发送和接受。
涉及的寄存器有:1)涉及的UART通道管脚设置寄存器如设置rGPHCON将GPH2、GPH3引脚的功能设为TXD0、RXD0;2)波特率设置寄存器rUBRDIVn(n=0~2);3)线控制寄存器rULCONn,主要用来选择每帧数据位和停止位宽度,奇偶校验模式及是否使用红外模式;4)控制寄存器rUCONn,用于选择UART时钟源、设置中断方式、接受超时时能、接受错误状态中断使能等;
5)FIFO设置寄存器rUFCONn与FIFO状态寄存器rUFSTATn;6)流量控制寄存器rUMCONn与流量状态寄存器rUMSTATn;7)发送/接受状态寄存器rUTRSTATn,用来表明数据是否已经发送完毕、是否已经接受到数据;8)错误状态寄存器rUERSTATn,用来表示各种错误是否发生如溢出错误、校验错误、帧错误等;9)发送缓冲数据寄存器rUTXHn与接受数据缓冲寄存器rURXHn。
4. 用中断方式实现串口驱动。
答:一种简单的利用中断方式实现的串口驱动设计:
1)接受串口数据函数
int recv_comData(char* dest, int count)
函数流程:首先设置rINTMSK打开串口接受中断,然后挂起等待一个标识数据接受完毕的全局变量IsReady变为真,然后从全局缓冲区Rxbuffer[MAX_LEN]复制count字节数据到dest所指的目标地址并返回;
当串口数据到达时,在相应的IRQ中断服务程序中,接受串口数据至缓冲区Rxbuffer[MAX_LEN],并设置全局变量IsReady为真值,然后清除并关闭串口接受中断。
2)发送串口数据函数
int send_comData(char* src, int count)
函数流程:将src指向的count字节长的源数据拷贝至发送缓冲区Txbuffer[MAX_LEN](以’\0’作为数据结束标志),使能串口发送中断,然后挂起等待一个标识数据发送完毕的全局变量IsOver变为真,发送完毕后函数返回。
缓冲区变空产生发送中断,在使能中断的情况下,在相应的IRQ中断服务程序中,将缓冲区Txbuffer[MAX_LEN]中的有效数据写入发送寄存器或FIFO,并设置全局变量IsOver为真值,然后清除并关闭串口发送中断。
6
第二篇:北航ARM9实验报告1
串口通讯实验
一、 实验目的
1. 掌握ARM的串行口工作原理。
2. 学习编程实现ARM的UART通讯。
3. 掌握S3C2410寄存器配置方法。
二、 实验内容
实现查询方式串口的收发功能。接收来自串口(通过超级终端)的字符并将接收到的字符发送到超级终端。
三、 预备知识
1. 了解ADS集成开发环境的基本功能。
2. 学习串口通讯的基本知识。
3. 熟悉S3C2410串口有关的寄存器。
四、 实验设备
硬件:2410s教学实验箱、ARM920T的JTAG仿真器、串口连接线。 软件:ARM ADS1.2集成开发环境、超级终端通讯程序。
五、 实验步骤
1. 新建工程,将启动所需要的基础文件添加至工程中,如启动文件startup.s、地址文件2410addr.s、reg2410.h和分散加载文件scat_ram.scf等。
2. 定义用到的与UART有关的各个寄存器地址和一些常数: /*涉及的GPIP寄存器*/
#define rGPHCON (*(volatile unsigned long *)0x56000070) #define rGPHDAT (*(volatile unsigned long *)0x56000074) #define rGPHUP (*(volatile unsigned long *)0x56000078)
/*UART 寄存器*/
#define rULCON0 (*(volatile unsigned long *)0x50000000) #define rUCON0 (*(volatile unsigned long *)0x50000004) #define rUFCON0 (*(volatile unsigned long *)0x50000008) #define rUMCON0 (*(volatile unsigned long *)0x5000000c) #define rUTRSTAT0 (*(volatile unsigned long *)0x50000010) #define rUBRDIV0 (*(volatile unsigned long *)0x50000028)
#define RdURXH0() (*(volatile unsigned char *)0x50000024) #define WrUTXH0(ch) \
1
(*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)
/*定义常数:PCLK及波特率*/
#define PCLK 5000000 // 50MHZ
#define UART_CLK PCLK // the clock source of UART0 is setted as PCLK #define UART_BAUD_RATE 115200 // baud rate
#define UART_BRD ((UART_CLK/(UART_BAUD_RATE * 16)) - 1)
3. 编写串口初始化函数:
/* ***************************************************** * Name: uart0_init(void)
* Description: initial the UART0: 115000,BN1, no modem contrl /* ***************************************************** void uart0_init(void)
{
rGPHCON |= 0xa0; // GPH2 = TXD0 , GPH3 = RXD0
rGPHUP = 0x0c; // GPH2,3 pull-up
rULCON0 = 0x03; // 8N1
rUCON0 = 0x05; // look-up way
rUFCON0 = 0x00; // not use FIFO
rUMCON0 = 0x00; // not use moden-contrl
rUBRDIV0 = UART_BRD; // baud_rate
}
4. 编写串口驱动函数:
/* ***************************************************** * Name: Uart_SendByten
* Description: 发送字节数据data到串口0
/* ***************************************************** void Uart_SendByten(U8 data)
{
while(!(rUTRSTAT0 & 0x4)); //Wait until THR is empty.
hudelay(10);
WrUTXH0(data);
}
/* ********************************************************** * Name: Uart_SendByten
* Description: 接受串口0一字节数据拷贝至Revdata所指地址 /* ********************************************************* char Uart_Getchn(char* Revdata, int timeout)
{
while(!(rUTRSTAT0 & 0x1)); //Receive data read
*Revdata=RdURXH0();
return TRUE;
}
2
5. 编写主函数:
/* ********************************************************** * Name: main
* Description: 从串口0接受数据并显示在超级终端
/* ********************************************************* int main(void)
{
char c1[1];
char err;
ARMTargetInit(); // do target (uHAL based ARM system) initialisation // uart0_init(); //串口0寄存器及相关GPIO初始化
while(1)
{
Uart_SendByten(0xa); //换行
Uart_SendByten(0xd); //回车
err=Uart_Getchn(c1,0); //从串口0采集数据
Uart_SendByten(c1[0]); //显示采集的数据
}
}
六、 实验思考
1. 232串行通讯的数据格式是什么?
RS-232属于“异步传输”,在传送数据时,并不需要另外使用一条传输线来传送同步信号,不过必须在每一组数据的前后都加上同步信号,把同步信号与数据混和之后,使用同一条传输线来传输。从低位到高位的一帧数据格式为:
---------------------------------------------------------------------------------------
起始位(Start)+数据位(Data)+奇偶校验位(Parity)+停止位(Stop)
----------------------------------------------------------------------------------------
其中起始位固定为一个比特,停止位则可以是1、1.5或者是2比特(传送与接受一致),数据位可以设置为7、8或者9,奇偶校验位可以设置为无(N)、奇(O)或者偶(E),奇偶校验位可以使用数据中的比特。
2. 串行通讯最少需要几根线,分别如何连接?
以9芯D型插头为例,至少需要3根数据线:串口的2脚(发送数据TXD)与另一串口的3脚(接收数据RXD)连接,同时两串口的5脚(信号地)连接在一起。
3. ARM的串行口有几个,相应的寄存器是什么?
2410/2330自带3个UART端口通道,每个通道都可以工作于中断或者DMA模式,且都有16字节的FIFO用于数据发送和接受。
涉及的寄存器有:1)涉及的UART通道管脚设置寄存器如设置rGPHCON将GPH2、GPH3引脚的功能设为TXD0、RXD0;2)波特率设置寄存器rUBRDIVn(n=0~2);3)线控制寄存器rULCONn,主要用来选择每帧数据位和停止位宽度,奇偶校验模式及是否使用红外模式;4)控制寄存器rUCONn,用于选择UART时钟源、设置中断方式、接受超时时能、接受错误状态中断使能等; 3
5)FIFO设置寄存器rUFCONn与FIFO状态寄存器rUFSTATn;6)流量控制寄存器rUMCONn与流量状态寄存器rUMSTATn;7)发送/接受状态寄存器rUTRSTATn,用来表明数据是否已经发送完毕、是否已经接受到数据;8)错误状态寄存器rUERSTATn,用来表示各种错误是否发生如溢出错误、校验错误、帧错误等;9)发送缓冲数据寄存器rUTXHn与接受数据缓冲寄存器rURXHn。
4. 用中断方式实现串口驱动。
答:一种简单的利用中断方式实现的串口驱动设计:
1)接受串口数据函数
int recv_comData(char* dest, int count)
函数流程:首先设置rINTMSK打开串口接受中断,然后挂起等待一个标识数据接受完毕的全局变量IsReady变为真,然后从全局缓冲区Rxbuffer[MAX_LEN]复制count字节数据到dest所指的目标地址并返回;
当串口数据到达时,在相应的IRQ中断服务程序中,接受串口数据至缓冲区Rxbuffer[MAX_LEN],并设置全局变量IsReady为真值,然后清除并关闭串口接受中断。
2)发送串口数据函数
int send_comData(char* src, int count)
函数流程:将src指向的count字节长的源数据拷贝至发送缓冲区Txbuffer[MAX_LEN](以’\0’作为数据结束标志),使能串口发送中断,然后挂起等待一个标识数据发送完毕的全局变量IsOver变为真,发送完毕后函数返回。
缓冲区变空产生发送中断,在使能中断的情况下,在相应的IRQ中断服务程序中,将缓冲区Txbuffer[MAX_LEN]中的有效数据写入发送寄存器或FIFO,并设置全局变量IsOver为真值,然后清除并关闭串口发送中断。
4