1、 单片机实验报告 实验一 数码管实验 一、 实验目的 1. 了解数码管的显示原理; 2. 掌握JXARM9-2440 中数码管显示编程方法。 二、 实验原理 7段LED由7个发光二极管按“日”字形排列,所有发光二极管的阳极连在一起称共阳极接法,阴极连在一起称为共阴极接法。 LED显示器的接口一般有静态显示与动态显示接口两种方式。 本实验中采用的是动态显示接口,其中数码管扫描控制地址为0x20007000,位0-位5每位分别对应一个数码
2、管,将其中某位清0 来选择相应的数码管,地址0x20006000 为数码管的数据寄存器。数码管采用共阳方式,向该地址写一个数据就可以控制LED 的显示,其原理图如图所示。 三、 实验内容 1、六个数码管同时正向显示0-F ,然后反向显示F-0。 2、在六个数码管上依次显示“HELLO”,可分辨出轮流显示。 3、在六个数码管上依次显示“HELLO”,分辨不出轮流显示。。 4*、在每个数码管上递增显示0-9 。步骤同上。 四、 实验程序 实验1: /***************************************************************
3、/ /*文件名称: LEDSEG7.C */ /*实验现象: 数码管依次显示出0、1,2、……9、a、b、C、d、E、F */ /*******************************************************************/ #define U8 unsigned char unsigned char seg7table[16] = { /* 0 1 2 3 4
4、 5 6 7*/ 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, /* 8 9 A B C D E F*/ 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e, }; void Delay(int time); /*********************************************
5、/ /* 函数说明: JXARM9-2410 7段构共阳数码管测试 */ /* 功能描述: 依次在7段数码管上显示0123456789ABCDEF */ /* 返回代码: 无 */ /* 参数说明: 无 */ /********************************
6、/ void Test_Seg7(void) { int i; *((U8*)0x20007000)=0x00; /*六个数码管都亮*/ for( ; ;) { for(i=0;i<0x10;i++) /*数码管从0到F依次显示出来*/ { *((U8*)0x20006000)=seg7table[i]; Delay(1000); } for(0xf;i>=0x0;i--) /*数码管从F到0依次显示出来*/ { *((U8*)0
7、x20006000)=seg7table[i]; Delay(1000); } } // TODO } /*****************************************************************/ /* Function name : 循环延时子程序 */ /* Description : 循环 'time' 次 */ /* Return type :void
8、 */
/* Argument : 循环延时计数器 */
/*****************************************************************/
void Delay(int time)
{
int i;
int delayLoopCount=1000;
for(;time>0;time--);
for(i=0;i 9、/
/*文件名称: LEDSEG7.C */
/*实验现象: 数码管依次显示出0、1,2、……9、a、b、C、d、E、F */
/*******************************************************************/
#define U8 unsigned char
unsigned char seg7tabl 10、e[4]= {/*O L E H*/ 0xC0,0xC7,0x86,0x89};
void Delay(int time);
/*******************************************************************/
/* 函数说明: JXARM9-2410 7段构共阳数码管测试 */
/* 功能描述: 依次在7段数码管上显示0123456789ABCDEF */
/* 返回代码: 无 11、 */
/* 参数说明: 无 */
/******************************************************************/
void Test_Seg7(void)
{
for( ; ;)
{
*((U8*)0x20007000)=0x3E; //**111110
*((U8*)0x20006000)=seg7table[0]; //第一个数码管显示O
Delay(1 12、000);
*((U8*)0x20007000)=0x3D; //**111101
*((U8*)0x20006000)=seg7table[1]; //第二个数码管显示L
Delay(1000);
*((U8*)0x20007000)=0x3B; //**111011
*((U8*)0x20006000)=seg7table[1]; //第三个数码管显示L
Delay(1000);
*((U8*)0x20007000)=0x37; //**110111
*((U 13、8*)0x20006000)=seg7table[2]; //第四个数码管显示E
Delay(1000);
*((U8*)0x20007000)=0x2F; //**101111
*((U8*)0x20006000)=seg7table[3]; //第五个数码管显示H
Delay(1000);
}
}
// TODO
/*******************************************************************/
/* Function name 14、 : 循环延时子程序 */
/* Description : 循环 'time' 次 */
/* Return type :void */
/* Argument : 循环延时计数器 */
/************************************************ 15、/
void Delay(int time)
{
int i;
int delayLoopCount=1000;
for(;time>0;time--);
for(i=0;i 16、 数码管依次显示出0、1,2、……9、a、b、C、d、E、F */
/*******************************************************************/
#define U8 unsigned char
unsigned char seg7table[4]= {/*O L E H*/ 0xC0,0xC7,0x86,0x89};
void Delay(int time);
/******************************************************************* 17、/
/* 函数说明: JXARM9-2410 7段构共阳数码管测试 */
/* 功能描述: 依次在7段数码管上显示0123456789ABCDEF */
/* 返回代码: 无 */
/* 参数说明: 无 */
/****************************************************** 18、/
void Test_Seg7(void)
{
for( ; ;)
{
*((U8*)0x20007000)=0x3E; //**111110
*((U8*)0x20006000)=seg7table[0]; //第一个数码管显示O
Delay(5);
*((U8*)0x20007000)=0x3D; //**111101
*((U8*)0x20006000)=seg7table[1]; //第二个数码管显示L
Delay(5);
*((U8*)0x20 19、007000)=0x3B; //**111011
*((U8*)0x20006000)=seg7table[1]; //第三个数码管显示L
Delay(5);
*((U8*)0x20007000)=0x37; //**110111
*((U8*)0x20006000)=seg7table[2]; //第四个数码管显示E
Delay(5);
*((U8*)0x20007000)=0x2F; //**101111
*((U8*)0x20006000)=seg7ta 20、ble[3]; //第五个数码管显示H
Delay(5);
}
}
// TODO
/*******************************************************************/
/* Function name : 循环延时子程序 */
/* Description : 循环 'time' 次 */
/* Return type :void 21、 */
/* Argument : 循环延时计数器 */
/******************************************************************/
void Delay(int time)
{
int i;
int delayLoopCount=5;
for(;time>0;time--);
for(i=0;i 22、析
实验1六个数码管从O到F依次显示,然后再反向显示,分析:首先通过地址20007000选择哪个数码管亮,通过地址20006000决定数码管输出的内容,再通过循环可完成轮流显示;实验2数码管从左到右依次显示HELLO,实验3数码管同时显示HELLO,分析:Delay数值的改变导致频率变化,从而可以产生两种效果。
六、 实验总结
1.由于数码管为共阳极,小数点为最高位,A为最低位,所以显示内容一定要计算正确。
2.循环条件要选择正确。
实验二 键盘输入实验
一、 实验目的
1. 学习键盘驱动原理;
2. 掌握通过CPU 的I/O拓展键盘的方法
二、 实验原理
1 23、键盘实现方案
1)采用专门的芯片实现键盘扫描
2)采用软件实现键盘扫描
2.软键盘实现方案
当开关打开时,通过处理器的I/O 口的一个上拉电阻提供逻辑1;当开关闭合时,处理器的I/O 口的输入将被拉低到逻辑0。
3.按键抖动
开关并不完善,因为当它们被按下或者被释放时,并不能够产生一个明确的1或者0。尽管触点可能看起来稳定而且很快地闭合,但与微处理器快速的运行速度相比,这种动作是比较慢的。当触点闭合时,其弹起就像一个球。弹起效果将产生如下图所示的好几个脉冲。弹起的持续时间通常将维持在5ms~30ms 之间。
4.矩阵键盘电路
1) 一个瞬时接触开关(按钮)放置在每一 24、行与每一列的交叉点。每一行由一个输出端口的一位驱动,每一列由一个电阻器上拉且供给输入端口一位。
2) 键盘扫描过程就是让微处理器按有规律的时间间隔查看键盘矩阵,以确定是否有键被按下。
3)一旦处理器判定有一个键按下,键盘扫描软件将过滤掉抖动并且判定哪个键被按下。
4)每个键被分配一个称为扫描码的唯一标识符。应用程序利用该扫描码,根据按下的键来判定应该采取什么行动,换句话说,扫描码将告诉应用程序按下哪个键。
5.键盘扫描算法
1) 初始化:所有的行(输出端口)被强行设置为低电平。
2) 在没有任何键按下时,所有的列(输入端口)将读到高电平。
3) 任何键的闭合将造成其中的一列变 25、为低电平。
4) 一旦检测到有键被按下,就需要找出是哪一个键。过程很简单,微处理器只需在其中一行上输出一个低电平。如果它在输入端口上发现一个0值,微处理器就知道在所选择行上产生了键的闭合。
6.一旦检测到有键被按下,就需要找出是哪一个键。过程很简单,微处理器只需在其中一行上输出一个低电平。如果它在输入端口上发现一个0值,微处理器就知道在所选择行上产生了键的闭合
JXARM9-2440具有4×4的软键盘。原理图如下:
三、 实验内容
1、学习与分析例程中的各个程序以及主要函数,以进一步理解键盘的工作原理。
3
2
1
0
6
5
4
F
9
8
7
E
A 26、
B
C
D
2、编写程序语句,获取按键值,在串口显示。
3、程序开发,使按键值按照如图的顺序显示出来。
4、*程序开发,将按键值在数码管上显示(自行设计形式)。
5、*自行设计与开发。
四、 实验程序
实验1:
#include "def.h"
#include "2410lib.h"
#include "option.h"
#include "2410addr.h"
#include "interrupt.h"
/********************************************************************
// F 27、unction name : Main
// Description : JXARM9-2410 键盘实验主程序
// 实现功能:
// Return type : void
// Argument : void
*********************************************************************/
void Main(void)
{
/* 配置系统时钟 */
ChangeClockDivider(2,1);
U32 mpll_val = 28、0 ;
mpll_val = (92<<12)|(1<<4)|(1);
ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);
/* 初始化端口 */
Port_Init();
/* 初始化串口 */
Uart_Init(0,115200);
Uart_Select(0);
/* 打印提示信息 */
PRINTF("\n---键盘测试程序---\n");
PRINTF("\n请将UART 29、0与PC串口进行连接,然后启动超级终端程序(115200, 8, N, 1)\n");
/* 开始回环测试 */
while(1)
{
unsigned char ch;
ch=Key_GetKeyPoll();
// TODO
// 获取键值
if(ch != 0)
{
PRINTF("\r'%c'键按下", ch);
}
}
}
实验2:
#include 30、include "timer.h"
#include "interrupt.h"
#define RECV_CMD_MAX_BUF 2048
char recv_buf[RECV_CMD_MAX_BUF];
int recv_read = 0;
int recv_write = 0;
char key_recv_buf[RECV_CMD_MAX_BUF];
int key_recv_read = 0;
int key_recv_write = 0;
// 键盘扫描
int timer1_count = 0;
enum KEYBOARD_SCAN 31、STATUS
{
KEYBOARD_SCAN_FIRST,
KEYBOARD_SCAN_SECOND,
KEYBOARD_SCAN_THIRD,
KEYBOARD_SCAN_FOURTH
};
int row = 0;
extern unsigned char output_0x10000000;
unsigned char ascii_key, input_key[4], input_key1[4], key_mask = 0x0F;
unsigned char* keyboard_port_scan = (unsigned char*)0x2000C000; 32、
unsigned char* keyboard_port_value = (unsigned char*)0x2000C000;
int keyboard_scan_status[4] = {
KEYBOARD_SCAN_FIRST,
KEYBOARD_SCAN_FIRST,
KEYBOARD_SCAN_FIRST,
KEYBOARD_SCAN_FIRST
};
char key_get_char(int 33、row, int col)
{
char key = 0;
switch( row )
{
case 0:
if((col & 0x01) == 0) key = 'D';
else if((col & 0x02) == 0) key = 'E';
else if((col & 0x04) == 0) key = 'F';
else if((col & 0x08) == 0) key = '0';
break;
case 1:
if((col & 0x01) == 0) key = 'C';
else if((co 34、l & 0x02) == 0) key = '7';
else if((col & 0x04) == 0) key = '4';
else if((col & 0x08) == 0) key = '1';
break;
case 2:
if((col & 0x01) == 0) key = 'B';
else if((col & 0x02) == 0) key = '8';
else if((col & 0x04) == 0) key = '5';
else if((col & 0x08) == 0) key = '2';
brea 35、k;
case 3:
if((col & 0x01) == 0) key = 'A';
else if((col & 0x02) == 0) key = '9';
else if((col & 0x04) == 0) key = '6';
else if((col & 0x08) == 0) key = '3';
break;
default:
break;
}
return key;
}
/******************************************************************* 36、
// Function name : recv_key
// Description : 将获取的键值加入按键缓冲区
// Return type : void
// Argument : int key
*********************************************************************/
void recv_key(int key)
{
key_recv_buf[key_recv_write] = key;
key_recv_write ++;
if(key_recv_write 37、>= RECV_CMD_MAX_BUF)
key_recv_write = 0;
if(key_recv_write == key_recv_read)
{
// 缓冲区以满
key_recv_read ++;
if(key_recv_read >= RECV_CMD_MAX_BUF)
key_recv_read = 0;
}
}
/********************************************************************
// Function name : Kbd_Scan
// De 38、scription : 定时器1中断服务程序,用于扫描键盘,每隔10ms一次中断
// Return type : void
// Argument : void
*********************************************************************/
void Kbd_Scan(void)
{
int loop.t = row, bexit = 0;
int temp;
// 键盘扫描
for( loop.t = row; loop.t < row + 4; loop.t ++)
39、{
if(loop.t >= 4)
temp = loop.t - 4;
else
temp = loop.t;
switch(keyboard_scan_status[temp])
{
case KEYBOARD_SCAN_FIRST:
*keyboard_port_scan = output_0x10000000 & (~(0x00000001< 40、it = 1;
break;
case KEYBOARD_SCAN_SECOND:
input_key[temp] = (*keyboard_port_value) & key_mask; /*并获取第一次扫描值*/
if(input_key[temp] == key_mask)
keyboard_scan_status[temp] = KEYBOARD_SCAN_FIRST; /* 没有按键,回到开始状态 */
else
{
keyboard_scan_status[temp] = KEYBOARD_S 41、CAN_THIRD; /* 有按键 */
bexit = 1;
}
break;
case KEYBOARD_SCAN_THIRD:
if (((*keyboard_port_value) & key_mask) != input_key[temp])
keyboard_scan_status[temp] = KEYBOARD_SCAN_FIRST;
else
{
ascii_key = key_get_char(temp, input_key[temp]);
keyboard_ 42、scan_status[temp] = KEYBOARD_SCAN_FOURTH;
*keyboard_port_scan = output_0x10000000 & (~(0x00000001< 43、[temp] == key_mask)
{
// get a key
recv_key(ascii_key);
keyboard_scan_status[temp] = KEYBOARD_SCAN_FIRST;
}else
{
*keyboard_port_scan = output_0x10000000 & (~(0x00000001< 44、t)
break;
}
row = temp;
}
/********************************************************************
// Function name : Key_GetKey
// Description : 如果有键按下返回键,否则返回0
// Return type : char
// Argument :
*********************************************************************/ 45、
char Key_GetKey()
{
char ch;
if(key_recv_write == key_recv_read)
{
/* no key found */
ch = 0;
}else
{
ch = key_recv_buf[key_recv_read];
key_recv_read ++;
if(key_recv_read >= RECV_CMD_MAX_BUF)
key_recv_read = 0;
}
return ch;
}
/****************************** 46、
// Function name : Key_GetKeyPoll(查询方式)
// Description : 如果有键按下返回键,否则返回0
// Return type : char
// Argument :
*********************************************************************/
char Key_GetKeyPoll()
{
int row;
unsigned char ascii_ke 47、y, input_key, input_key1, key_mask = 0x0F;
for( row = 0; row < 4; row++)
{
*keyboard_port_scan = output_0x10000000 & (~(0x00000001< 48、) continue; /* 没有按键 */
/* 延时,再次获取扫描值,如果两次的值不等,则认为是一个干扰 */
Delay(3);
if (((*keyboard_port_value) & key_mask) != input_key) continue;
// 等待按键松开
while(1)
{
*keyboard_port_scan = output_0x10000000 & (~(0x00000001< 49、put_key1 = (*keyboard_port_value) & key_mask; /*并获取第一次扫描值*/
if(input_key1 == key_mask) break; /* 没有按键 */
}
ascii_key = key_get_char(row, input_key); /* 查表 */
return ascii_key; /* 显示结果 */
}
return 0;}
实验3:
/* 包含文件 */
#include "def.h"
#include "2410lib.h 50、"
#include "option.h"
#include "2410addr.h"
#include "interrupt.h"
#include






