欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于Proteus与keil联合仿真的51单片机学习记录(二)

程序员文章站 2022-03-26 18:23:29
...

1.设计要求

    使用单片机P0端口实现8个LED的流水灯控制。

2.程序设计

   流水灯又称跑马灯,可使用循环移位指令实现。使用汇编指令编写程序时,需使用RL A指令,其程序流程图如下图所示。使用C语言编写程序时,需使用j=j<<1指令,且将移位初值置为0x01,移位后的数值需取反再送给P0端口。

基于Proteus与keil联合仿真的51单片机学习记录(二)

#include "reg51.h"
#define uint unsigned int
#define uchar unsigned char
void delay(void)
{
	uchar i,j,k;
	for(k=10;k>0;k--)
	  {
	    for(j=200;j>0;j--)
	      {
		      for(i=230;i>0;i--);
	      }
    }
}
void main(void)
{
	uchar i,j;
	
	P0=0xFF;
	while(1)
	{
		j=0x01;
		for(i=0;i<8;i++)
		{
			P0=~j;
			delay();
			j=j<<1;
		}
	}
}

3.硬件设计

基于Proteus与keil联合仿真的51单片机学习记录(二)

4.知识补充(个人笔记(转载))

C语言位操作

原文地址 https://blog.csdn.net/sha*a/article/details/5783582

C语言的设计具备了汇编语言的运算能力,它支持全部的位操作符。位操作符是对字节或字中的位进行测试、置位或移位处理,在对微处理器的编程中,特别适合对寄存器、I/O端口进行操作。

6种伟操作符:

(1) & :按位“与”——仅当两个操作数为1时,结果为1,否则为0。如:1000 1000 & 1000 0001 = 1000 0000;

(2) | :按位“或”——仅当两个操作数为0时,结果为0,否则为1。如:1000 1000 | 1000 0001 = 1000 1001;

(3) ^:按位“异或”——仅当两个操作数不同时,相应的输出结果才为1,否则为0。

           如:1000 1000 ^ 1000 0001 = 0000 1001 ;

(4) ~ :“取反”——把1置为0,0置为1。如:~1000 1000 = 0111 0111;

(5) <<: “左移”——将变量的各位按要求向左移动若干位。如:0000 1000 <<3 = 0100 0000;

(6) >>: “右移”——将变量的各位按要求向右移动若干位。如:0000 1000>>3=0000 0001;

位运算符的应用:

(1)直接交换两个变量的值

例如,若有变量a = 3,b = 4,想要交换它们的值,可以做如下一组操作:

a ^ = b

b ^ = a

a ^ = b

首先,a ^ = b:

 a    0000 0011

^ b 0000 0100

a = 0000 0111

其次,b ^ = a:

 b    0000 0100

^ a 0000 0111

b = 0000 0011

最后,a ^ = b:

 a    0000 0111

^ b 0000 0011

a = 0000 0100

这样,a、b两个变量中的值就进行了对调。

(2)快速乘除运算

移位操作可用于整数的快速乘除运算,左移一位等效于乘2,而右移一位等效于除以2。

如:x = 7, 二进制表达为:0000 0111,

x < < 1 0000 1110,相当于: x =2*7=14,

x < < 3 0111 0000,相当于: x=1422*2=112

x < < 2 1100 0000, x= 192

在作第三次左移时,其中一位为1的位移到外面去了,而左边只能以0补齐,因而便不等于11222=448,而是等于192了。当x按刚才的步骤反向移动回去时,就不能返回到原来的值了,因为左边丢掉的一个1,再也不能找回来了:

x > > 2 0011 0000, x=48

x > > 3 0000 0110 x=48/8=6

x > > 1 0000 0011 x=6/2=3

(3)将寄存器指定位置为1

PORTA |= (1<<n) 将porta的第n为置为1,其他为不变。比如说,你如果想将第4位置1,就使用:

PORTA | = (1<< 4) 就行了。当然,也可以使用:

PORTA | = (1<< 7) | (1<< 4 ) | (1<< 0) 这样的指令一次将设第8、5和1位置1,但又不影响到其它位的状态。

(4)将寄存器指定位置为0

PORTA &= ~(1<<n )

这条指令将寄存器的任意位清0,而又不影响其它位的现有状态。比如说,你如果想将第4位清0,就使用:

PORTA & = ~ (1<< 4) 就行了。

/*
位操作
Description
假设你工作在一个32位的机器上,你需要将某一个外设寄存器的第X位设置成0(最低位为第0位,最高位为第31位),
将第Y位开始的连续三位设置成110(从高位到低位的顺序),而其他位保持不变。对给定的寄存器值R,及X,Y,
编程计算更改后的寄存器值R。
Input
仅一行,包括R,X,Y,以逗号","分隔,R为16进制表示的32位整数,X,Y在0-31之间且Y>=3,(Y-X)的绝对值>=3,保证两次置位不会重合
Output
更改后的寄存器值R(16进制输出)
Sample Input
12345678,0,3
Sample Output
1234567c
Source
 */
#include <stdio.h>
int main()
{
 int R, X, Y;
 scanf("%x,%d,%d",&R,&X,&Y);
 R &= ~(1<<X);       // 将R的第X位设置为0
 R |= (1<<Y);        // 将R的第Y位设置为1
 Y--;
 R |= (1<<Y);        // 将R的第Y-1位设置为1
 Y--;
 R &= ~(1<<Y);       // 将R的第Y-2位设置为0
 printf("%x/n",R);
 return 0;
}

以上内容来自转载,自已往后慢慢研习。

相关标签: 控制