资源描述
单片机实验报告
实验一 数码管实验
一、 实验目的
1. 了解数码管的显示原理;
2. 掌握JXARM9-2440 中数码管显示编程方法。
二、 实验原理
7段LED由7个发光二极管按“日”字形排列,所有发光二极管的阳极连在一起称共阳极接法,阴极连在一起称为共阴极接法。
LED显示器的接口一般有静态显示与动态显示接口两种方式。
本实验中采用的是动态显示接口,其中数码管扫描控制地址为0x20007000,位0-位5每位分别对应一个数码管,将其中某位清0 来选择相应的数码管,地址0x20006000 为数码管的数据寄存器。数码管采用共阳方式,向该地址写一个数据就可以控制LED 的显示,其原理图如图所示。
三、 实验内容
1、六个数码管同时正向显示0-F ,然后反向显示F-0。
2、在六个数码管上依次显示“HELLO”,可分辨出轮流显示。
3、在六个数码管上依次显示“HELLO”,分辨不出轮流显示。。
4*、在每个数码管上递增显示0-9 。步骤同上。
四、 实验程序
实验1:
/*******************************************************************/
/*文件名称: 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 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);
/*******************************************************************/
/* 函数说明: JXARM9-2410 7段构共阳数码管测试 */
/* 功能描述: 依次在7段数码管上显示0123456789ABCDEF */
/* 返回代码: 无 */
/* 参数说明: 无 */
/*******************************************************************/
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*)0x20006000)=seg7table[i];
Delay(1000);
}
}
// TODO
}
/*****************************************************************/
/* Function name : 循环延时子程序 */
/* Description : 循环 'time' 次 */
/* Return type :void */
/* Argument : 循环延时计数器 */
/*****************************************************************/
void Delay(int time)
{
int i;
int delayLoopCount=1000;
for(;time>0;time--);
for(i=0;i<delayLoopCount;i++);
}
实验2:
/*******************************************************************/
/*文件名称: LEDSEG7.C */
/*实验现象: 数码管依次显示出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);
/*******************************************************************/
/* 函数说明: JXARM9-2410 7段构共阳数码管测试 */
/* 功能描述: 依次在7段数码管上显示0123456789ABCDEF */
/* 返回代码: 无 */
/* 参数说明: 无 */
/******************************************************************/
void Test_Seg7(void)
{
for( ; ;)
{
*((U8*)0x20007000)=0x3E; //**111110
*((U8*)0x20006000)=seg7table[0]; //第一个数码管显示O
Delay(1000);
*((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
*((U8*)0x20006000)=seg7table[2]; //第四个数码管显示E
Delay(1000);
*((U8*)0x20007000)=0x2F; //**101111
*((U8*)0x20006000)=seg7table[3]; //第五个数码管显示H
Delay(1000);
}
}
// TODO
/*******************************************************************/
/* Function name : 循环延时子程序 */
/* Description : 循环 'time' 次 */
/* Return type :void */
/* Argument : 循环延时计数器 */
/*******************************************************************/
void Delay(int time)
{
int i;
int delayLoopCount=1000;
for(;time>0;time--);
for(i=0;i<delayLoopCount;i++);
}
实验3:
/*******************************************************************/
/*文件名称: LEDSEG7.C */
/*实验现象: 数码管依次显示出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);
/*******************************************************************/
/* 函数说明: JXARM9-2410 7段构共阳数码管测试 */
/* 功能描述: 依次在7段数码管上显示0123456789ABCDEF */
/* 返回代码: 无 */
/* 参数说明: 无 */
/*****************************************************************/
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*)0x20007000)=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)=seg7table[3]; //第五个数码管显示H
Delay(5);
}
}
// TODO
/*******************************************************************/
/* Function name : 循环延时子程序 */
/* Description : 循环 'time' 次 */
/* Return type :void */
/* Argument : 循环延时计数器 */
/******************************************************************/
void Delay(int time)
{
int i;
int delayLoopCount=5;
for(;time>0;time--);
for(i=0;i<delayLoopCount;i++);
}
五、 结果与分析
实验1六个数码管从O到F依次显示,然后再反向显示,分析:首先通过地址20007000选择哪个数码管亮,通过地址20006000决定数码管输出的内容,再通过循环可完成轮流显示;实验2数码管从左到右依次显示HELLO,实验3数码管同时显示HELLO,分析:Delay数值的改变导致频率变化,从而可以产生两种效果。
六、 实验总结
1.由于数码管为共阳极,小数点为最高位,A为最低位,所以显示内容一定要计算正确。
2.循环条件要选择正确。
实验二 键盘输入实验
一、 实验目的
1. 学习键盘驱动原理;
2. 掌握通过CPU 的I/O拓展键盘的方法
二、 实验原理
1.键盘实现方案
1)采用专门的芯片实现键盘扫描
2)采用软件实现键盘扫描
2.软键盘实现方案
当开关打开时,通过处理器的I/O 口的一个上拉电阻提供逻辑1;当开关闭合时,处理器的I/O 口的输入将被拉低到逻辑0。
3.按键抖动
开关并不完善,因为当它们被按下或者被释放时,并不能够产生一个明确的1或者0。尽管触点可能看起来稳定而且很快地闭合,但与微处理器快速的运行速度相比,这种动作是比较慢的。当触点闭合时,其弹起就像一个球。弹起效果将产生如下图所示的好几个脉冲。弹起的持续时间通常将维持在5ms~30ms 之间。
4.矩阵键盘电路
1) 一个瞬时接触开关(按钮)放置在每一行与每一列的交叉点。每一行由一个输出端口的一位驱动,每一列由一个电阻器上拉且供给输入端口一位。
2) 键盘扫描过程就是让微处理器按有规律的时间间隔查看键盘矩阵,以确定是否有键被按下。
3)一旦处理器判定有一个键按下,键盘扫描软件将过滤掉抖动并且判定哪个键被按下。
4)每个键被分配一个称为扫描码的唯一标识符。应用程序利用该扫描码,根据按下的键来判定应该采取什么行动,换句话说,扫描码将告诉应用程序按下哪个键。
5.键盘扫描算法
1) 初始化:所有的行(输出端口)被强行设置为低电平。
2) 在没有任何键按下时,所有的列(输入端口)将读到高电平。
3) 任何键的闭合将造成其中的一列变为低电平。
4) 一旦检测到有键被按下,就需要找出是哪一个键。过程很简单,微处理器只需在其中一行上输出一个低电平。如果它在输入端口上发现一个0值,微处理器就知道在所选择行上产生了键的闭合。
6.一旦检测到有键被按下,就需要找出是哪一个键。过程很简单,微处理器只需在其中一行上输出一个低电平。如果它在输入端口上发现一个0值,微处理器就知道在所选择行上产生了键的闭合
JXARM9-2440具有4×4的软键盘。原理图如下:
三、 实验内容
1、学习与分析例程中的各个程序以及主要函数,以进一步理解键盘的工作原理。
3
2
1
0
6
5
4
F
9
8
7
E
A
B
C
D
2、编写程序语句,获取按键值,在串口显示。
3、程序开发,使按键值按照如图的顺序显示出来。
4、*程序开发,将按键值在数码管上显示(自行设计形式)。
5、*自行设计与开发。
四、 实验程序
实验1:
#include "def.h"
#include "2410lib.h"
#include "option.h"
#include "2410addr.h"
#include "interrupt.h"
/********************************************************************
// Function name : Main
// Description : JXARM9-2410 键盘实验主程序
// 实现功能:
// Return type : void
// Argument : void
*********************************************************************/
void Main(void)
{
/* 配置系统时钟 */
ChangeClockDivider(2,1);
U32 mpll_val = 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请将UART0与PC串口进行连接,然后启动超级终端程序(115200, 8, N, 1)\n");
/* 开始回环测试 */
while(1)
{
unsigned char ch;
ch=Key_GetKeyPoll();
// TODO
// 获取键值
if(ch != 0)
{
PRINTF("\r'%c'键按下", ch);
}
}
}
实验2:
#include <string.h>
#include "2410addr.h"
#include "2410lib.h"
#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_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;
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 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((col & 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';
break;
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;
}
/********************************************************************
// 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 >= 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
// Description : 定时器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 ++)
{
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<<temp)); /*将row列置低电平 */
keyboard_scan_status[temp] = KEYBOARD_SCAN_SECOND;
bexit = 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_SCAN_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_scan_status[temp] = KEYBOARD_SCAN_FOURTH;
*keyboard_port_scan = output_0x10000000 & (~(0x00000001<<temp)); /*将row列置低电平 */
bexit = 1;
}
break;
case KEYBOARD_SCAN_FOURTH:
input_key1[temp] = (*keyboard_port_value) & key_mask; /*并获取第一次扫描值*/
if(input_key1[temp] == key_mask)
{
// get a key
recv_key(ascii_key);
keyboard_scan_status[temp] = KEYBOARD_SCAN_FIRST;
}else
{
*keyboard_port_scan = output_0x10000000 & (~(0x00000001<<temp)); /*将row列置低电平 */
bexit = 1;
}
break;
}
if(bexit)
break;
}
row = temp;
}
/********************************************************************
// Function name : Key_GetKey
// Description : 如果有键按下返回键,否则返回0
// Return type : char
// Argument :
*********************************************************************/
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;
}
/********************************************************************
// Function name : Key_GetKeyPoll(查询方式)
// Description : 如果有键按下返回键,否则返回0
// Return type : char
// Argument :
*********************************************************************/
char Key_GetKeyPoll()
{
int row;
unsigned char ascii_key, input_key, input_key1, key_mask = 0x0F;
for( row = 0; row < 4; row++)
{
*keyboard_port_scan = output_0x10000000 & (~(0x00000001<<row)); /*将row列置低电平 */
Delay(3); /*延时 */
input_key = (*keyboard_port_value) & key_mask; /*并获取第一次扫描值*/
if(input_key == key_mask) continue; /* 没有按键 */
/* 延时,再次获取扫描值,如果两次的值不等,则认为是一个干扰 */
Delay(3);
if (((*keyboard_port_value) & key_mask) != input_key) continue;
// 等待按键松开
while(1)
{
*keyboard_port_scan = output_0x10000000 & (~(0x00000001<<row)); /*将row列置低电平 */
Delay(3);
input_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"
#include "option.h"
#include "2410addr.h"
#include "interrupt.h"
#include <stdio.h>
#include <math.h>
#define IIRNUMBER 2
#define U8 unsigned char
unsigned char table[16] = {
/* 0 1 2 3 4 5 6 7*/
0xc0, 0xf9, 0xa4, 0xb0, 0x99,
展开阅读全文