博文
【014】外中断0响应实例 [51](2006-06-29 22:15:00)
摘要:实验参考: 《单片机轻松入门》(周坚)
实验板: FB51A。(查看)
方法: 通过按键模拟外部中断的产生信号,用P0.0口接的LED作为中断响应。
实验现象:键按下时,P0.0口的LED亮灭交替。
电路如下:
在程序中,将中断0设置为下降沿触发:
org 0000h
ajmp start
org 0003h ; 外部中断地址入口
ljmp int_0 ; 转到真正的处理程序
org 30h
start: mov sp, #5fh ; 初始化堆栈
mov p0, #0ffh ; 灯全灭
mov p3, #0ffh ; P3口置高电平
setb IT0 ; 下降沿触发
setb EA ; 开总中断
setb EX0 ......
【013】查询方式按键 [51](2006-06-25 00:57:00)
摘要:实验参考: 笨笨工作室-实验六、查询方式按键。(查看)
实验板: FB51A。(查看)
实验目的: <1> 掌握读取外部按键时候应该注意的事项,掌握查询方式响应按键的方法。
<2> 掌握读取按键去抖动的方法。
<3> 掌握判直接寻址位转移指令jb,jnb的用法。
实验现象: 最右面的数码管初始显示0,每次按下外部按键K1执行加一,计数到9时重新回0。
单片机响应外部按键的方式有两种,一种是查询方式,一种是中断方式。
查询方式:单片机不断的查询是否有按键按下,如果有按键按下的话,就执行相应的程序,否则继续查询。
中断方式:单片机处理自己的工作,如果有按键按下,向单片机发出中断请求。单片机停下现在正在处理的工作,转去执行中断程序,执行之后回来继续刚才的工作。
本实验是用查询方式完成, 只用到一个键K1,每次按下,使第一位数码管加1显示,计数到9里重新回0。显示部分电路及查表显示方法参考:【005】数码管显示数字 和 【006】多位数码管动态显示。原理图如下:
由原理图知:当按键k1按下的时候,对应P1.0输入低电平。因此,我们要查询k1是否按下,只要检测到p1.0是低电平即可。 在查询键是否按下时,要注意按键的去抖动问题,关于键的消抖,见 【012】按键消抖 。
按上述方法编写程序:
org 0000h
start: mov p0, #48h ; 段码-显示0
mov p2, #01h ; 位码-选通第一位数码管
main: mov r7, #0ffh  ......
【012】按键消抖(2006-06-23 19:29:00)
摘要:参考: 《单片机原理及接口技术》(李朝青)
按键电路:常用的非编码键盘,每个键都是一个常开开关电路。
按键消抖:
通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,电压信号小型如下图。由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,如下图。抖动时间的长短由按键的机械特性决定,一般为5ms~10ms。这是一个很重要的时间参数,在很多场合都要用到。
按键稳定闭合时间的长短则是由操作人员的按键动作决定的,一般为零点几秒至数秒。键抖动会引起一次按键被误读多次。为确保CPU对键的一次闭合仅作一次处理,必须去除键抖动。在键闭合稳定时读取键的状态,并且必须判别到键释放稳定后再作处理。按键的抖动,可用硬件或软件两种方法。
<1> 硬件消抖:在键数较少时可用硬件方法消除键抖动。下图所示的RS触发器为常用的硬件去抖。
图中两个“与非”门构成一个RS触发器。当按键未按下时,输出为1;当键按下时,输出为0。此时即使用按键的机械性能,使按键因弹性抖动而产生瞬时断开(抖动跳开B),中要按键不返回原始状态A,双稳态电路的状态不改变,输出保持为0,不会产生抖动的波形。也就是说,即使B点的电压波形是抖动的,但经双稳态电路之后,其输出为正规的矩形波。这一点通过分析RS触发器的工作过程很容易得到验证。
<2> 软件消抖:如果按键较多,常用软件方法去抖,即检测出键闭合后执行一个延时程序,产生5ms~10ms的延时,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。当检测到按键释放后,也要给5ms~10ms的延时,待后沿抖动消失后才能转入该键的处理程序。......
〖003〗三位加法器 [Verilog HDL模块的基本概念](2006-06-16 21:36:00)
摘要:参考: 《CPLD与单片机综合应用技术》(周立功)
实验板: 网助二号
例 5.2.3
module adder(count, sum, a, b, cin);
input [2:0] a, b;
input cin;
output count;
output [2:0] sum;
assign {count, sum} = a + b + cin;
endmodule
★ 此例描述了一个名为adder的三位加法器,可根据2个三比特数a、b及进位(cin)计算出和(sum)以及向上进位(count)。 "{ }"是拼接符,把count和sum拼接为一个4位的信号。
如何验证其正确性呢?开始将a的3个端口接了三个拨码开关,b的3个端口接了三个按钮开关(因为板上资源只有4个拨码开关和4个按钮开关),将相加得到的和sum的三个端口接三个LED显示结果, 进位位count同样接LED显示是否有进位,进位cin置为0。虽然这样的接法可以通过开关输入两个加数,也能看到结果,得出该模块的正确性,但总觉得这么手工输入的办法有些蠢,也没有发挥这块板MCU+CPLD综合的优势,于是产生如下方案。
用51单片机的P0口低3位产生被加数a, P2口低3位产生加数b, 得到的和还有进位仍然通过LED显示。开始想用二重循环产生所有的组合,被加数有8种情况,加数有8种情况,共可得到8×8=64种组合,但这样一来即不容易验证,二来也没必要,所以最终决定将b数值确定为01h, 而a的值由000b递增为111b这8个状态,分别与b相加后得到结果为001b,010b,011b,……,111b(第7个结果),再加01h后将产生进位,与后三位合并后为1000b,每个状态后延时1s以便观察,如此循环。上述过程中前一级的进位cin接地,即始终为0。
51单片机程序:
org 0000h
start: mov p2, #01h
&......
〖002〗二选一多路器[Verilog HDL模块的基本概念](2006-06-10 16:01:00)
摘要:参考:《单片机与CPLD综合应用技术》(周立功)
实验板: 网助二号
从几个简单Verilog HDL程序了解Verilog HDL模块的特性。
例5.2.1
module muxtwo(out, a, b, sl);
input a, b, sl;
output out;
reg out;
always @ (sl or a or b)
if(!sl)
out = a;
else
out = b;
endmodule
这几天看了许多不常见的符号,正好拿来组成以下框图表示上述模块:
____
a ───┤ ╲
ㄧ ├─── out
b ───┤ ╱
 ̄ ̄ㄧ
sl ─────┘
由于Verilog HDL是与C语言类似的, 所以不难理解此模块muxtwo的作用。这是一个二选一多路器(想起了数电里学过的数据选择器,又叫多路选择器Multiplexer, 简写为MUX), 即选择由out端输出a还是b由sl电平决定。sl为0时输出out与a相同; 否则与b相同。"always @ (sl or a or b)"这一句表示只要sl,或a,或b其中有一个变化,就执行下面......
[061] 一个字符串是否包含另一个字符串(2006-06-03 13:51:00)
摘要:《C程序设计》(夏宝岚)
习题6.13 检查一个字符串中是否包含另一个字符串
#include <stdio.h>
#include <string.h>
void main ()
{
int i = 0;
int j = 0;
int k = 0; /* 偏移量&&累计已经匹配的长度 */
int flag = 0; /* 是否有匹配的字符串标志位, 1为真, 0为假 */
char m[50];
char s[50];
printf("Mother string: ");
gets(m);
printf("Son string: ");
gets(s);
for(i = 0; i < (int)strlen(m); i++)
{
for(j = 0; j < (int)strlen(s); j++)
{
if(s[j] == m[i + k]) /* 若匹配则记录已经匹配的个数k */
&......
[060] 连接两个字符串(2006-06-02 22:26:00)
摘要:《C程序设计》(夏宝岚)
6.9 编写程序,实现将两个字符串连接起来(不允许用strcat函数)。
思路:定义三个数组a[], b[], c[],a.b用于存放将要连接的两个字符串,c用于保存a,b连接后的串。主要就是通过对字符串结束标志'\0'的判断分别将两串合并。第一次循环用控制变量i将串a复制到c中,第二次循环由于b串要从0开始,所以引入另一控制变量j由0开始,继续写入c时控制量i要延续第一次循环的值,最后将串c结束标志'\0'写入即可。如下:
#include <stdio.h>
void main ()
{
int i = 0;
int j = 0;
char a[50];
char b[50];
char c[50];
printf("First string: ");
gets(a);
printf("Second string: ");
gets(b);
while(a[i] != '\0') /* 将a串中内容copy到c中 */
{
c[i] = a[i];
i++;
}
while(b[j] != '\0') /* 将b串中内容继续copy到c中 */
{
c[i] =......
[062] 杨辉三角的多种解法(2006-06-07 12:21:00)
摘要:《C程序设计》(夏宝岚)
习题6.5 编写程序,打印杨辉三角形(即二项式系数表)
在网上搜了一下关于杨辉三角的介绍,才知道原来这个数学三角并不是杨辉提出的,而是由一个叫做贾宪的人提出,大约在1050年他使用这个三角进行高次开方运算。南宋数学家杨辉在《详解九章算法》(1961年)记载并保存了“贾宪三角”,故称杨辉三角。杨辉在书中很确凿地载明:此图“出释锁算书,贾宪用此术”,所以后来都改称“贾宪三角”了。他所说的图叫做"开方作法本源图", 关于其详细介绍,见 贾宪三角一文。
杨辉三角的形式如下:
1
1 1
1 2 1
1 3 &nb......
[059] C语言中动态分配数组(一维)(2006-05-28 17:52:00)
摘要: 当初学Pascal的时候就想过这个问题:如何动态的定义及使用数组呢?记得一般用数组的时候都是先指定大小的。当时问老师,老师说是不可以的。后来又问了一位教C++的老师,他告诉我在C++里用new可以做到,一直不用C++,所以也不明白。今天在逛论坛时终于找到了C语言中的用法(看原贴):
int *a;
int N;
scanf("%d", &N);
a = (int *) malloc(N * sizeof(int));
....
free(a);
这样就动态分配了数组a[N]。数组的长度N可输入确定,也可用程序中的变量确定。但要注意程序结束后要用free()将其释放,否则内存会泄漏。
验证一下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i = 0;
int *a;
int N;
printf("Input array length: ");
scanf("%d", &N);
printf("\n");
a = (int *) malloc(N * sizeof(int));
for(i = 0; i < N; i++)
{
a[i......
【011】单片机开发中应掌握的原则(2006-05-28 16:59:00)
摘要:选自《单片机语言C51应用实战集锦(修订版)》(范风强)
在学习新的开发软件时,一定要先看帮助手册,买书要全面。多实践、焊电路板、编写以及调试,如只用软件模拟,与真正的实践还是有距离的。
一、总的原则
从技术的角度来看,单片机开发分为软件、硬件两部分。许多厂商在仿真机、编程器之后力推开发板,其目的就是要让开发者在开发过程中尽量少做硬件的工作,甚至不需要做硬件开发工作。这些板通常力求全面,功能很多,设计者把所有的功能都做上,用户要用什么功能就有相应的电路板。在进行开发时,总的原则是:
<1> 定位准确。应用目标锁定在什么层次、什么类型,需要哪些功能,不需要做的就不必花钱去做。
<2> 经过实践检验。所采用的技术必须是经过实践检验的成熟技术,这一点很重要。
<3> 简单性原则。如果所做的就是开关量控制,不涉及模拟量,就不必采用模拟量技术。如果能够用单片机实现的技术,就不要用外围电路去实现。尽量做到小型、简单、可靠、廉价。
<4> 使用单片机C语言编程。C语言是简洁、高效、而又最贴近硬件的高级编程语言。20世纪90年代初单片机C语言就已成熟为专业水平的高级语言,不应再有顾虑。当前厂商在推出新的单片机产品时纷纷配套C语言编译器。
<5> 如有可能,使用中、高档的单片机仿真工具。
二、软件原则
<1> 提高C语言编程代码的效率
用C语言进行单片机程序设计是单片机开发与应用的必然趋势。如果使用C编程时,要达到最高的效率,最好熟悉所使用的C编译器。先试验一下每条C语言编译后对应的汇编语言的语句行数,这样就可以很明确地知道效率。在今后编程的时候,使用编译效率最高的语句。
各厂家的C编译器都会一定的差异,故编译效率也会有所不同,优秀的嵌入式系统C编译器代码长度和执行时间仅比以汇编语言写的同样功能的程......