蓝桥杯(单片机组)学习笔记(二)-------位运算总结/定时器/中断/杂记

一.位运算*

1.位操作符
①位与&
(1)注意:位与符号是一个&,两个&&是逻辑与。

(2)真值表:1&0=0 1&1=1 0&0=0 0&1=0

用法:与1位与无变化,与0位与变成0
②位或|

(1)注意:位或符号是一个|,两个||是逻辑或。

(2)真值表:1|0=1 1|1=1 0|0=0 0|1=1

用法:与1位或变成1,与0位或无变化

③位取反~

(1)注意:C语言中位取反是~,C语言中的逻辑取反是!

(2)按位取反是将操作数的二进制位逐个按位取反(1变成0,0变成1);而逻辑取反是真(在C语言中只要不是0的任何数都是真)变成假(在C语言中只有0表示假)、假变成真。

实验:任何非0的数被按逻辑取反再取反就会得到1;

任何非0的数倍按位取反再取反就会得到他自己;

④位异或^

(1)位异或真值表:1^1=0 0^0=0 1^0=1 0^1=1

用法:与1位异或会取反,与0位异或无变化

NOTE:
注意~和^的区别。前者是给所有位取反的。后者可以完成给特定位取反。

⑤左移位<< 与右移位>>

对于无符号数,左移时右侧补0(相当于逻辑移位)
对于无符号数,右移时左侧补0(相当于逻辑移位)

对于有符号数,左移时右侧补0(叫算术移位,相当于逻辑移位)

对于有符号数,右移时左侧补符号位(如果正数就补0,负数就补1,叫算术移位)

二、使用位操作符操作寄存器

前提条件:比如说32位的寄存器,最低位为bit0,最高位为bit31

1、特定位清零用&

实例1:给定一个整型数a,清除a的bit15,保证其他位不变。

a = a & (~(1<<15)); 或者 a &= (~(1<<15));//给零才会清零,所以当移位到bit15时,会取反一下。

实例2、给定一个整形数a,清除a的bit15~bit23,保持其他位不变。

a = a & (~(0x1ff<<15)); 或者 a &= (~(0x1ff<<15));

实例3、给定一个整形数a,清除a的bit15 ~ bit23,bit3~bit5保持其他位不变。

a = a & (~(0x1ff<<15) | ~(0x07<<3)); 或者 a &= (~(0x1ff<<15) | ~(0x07<<3));

位取反的优先级高于左移的优先级

2、特定位 置1用 |

实例1:给定一个整型数a,设置a的bit3,保证其他位不变。

a = a | (1<<3) 或者 a |= (1<<3)

实例2、给定一个整形数a,设置a的bit3~bit7,保持其他位不变。

a = a | (0b11111<<3) 或者 a |= (0x1f<<3);

实例3、给定一个整形数a,设置a的bit3bit5,bit15bit23,保持其他位不变。

a = a | ((0x1ff<<15) | (0x07<<3)); 或者 a |= ((0x1ff<<15) | (0x07<<3));

蓝桥杯对锁存器进行清理,预处理

void All_Init(void)
{
	P2 = (P2 & 0X1F | 0X80);//第567位清零,Y4C LED选中
	P0 = 0XFF;//关闭LED
	
	P2 = (P2 & 0X1F | 0XA0);//Y5C  继电器
	P0 = 0X00;
	
	P2 = (P2 & 0X1F | 0XC0);//Y6C   SMG 位选
	P0 = 0X00;
	
	P2 = (P2 & 0X1F | 0XE0);//Y7C  SMG 段选
	P0 = 0XFF;
}

3、特定位取反用^

实例1、给定一个整形数a,对a的bit3~bit7取反,保持其他位不变。

a = a ^ (0b11111<<3) 或者 a ^= (0x1f<<3);

三、位操作符的其他应用示例

实例1、给定一个整形数a,取出a的bit3~bit8。

a &= (0x3f<<3);//先将这个数bit3~bit8不变,其余位全部清零。a >>= 3;//再将其右移3位得到结果

实例2、使用宏定义实现截取部分连续位(x的bit(n-1)到bit(m-1)取出来 n<m)

note:假设最右边(bit0)为第1位

#define GETBITS(x, n, m) ((x & ((0U)<<(m-n+1))<<(n-1)) >> (n-1))

这个宏分为2部分:

(x & ((0U)<<(m-n+1))<<(n-1)) >> (n-1)

左边部分实现的功能其实是:bit(n-1)到bit(m-1)不变,其他的清零

右边部分实现的功能其实是:右移n位得到结果

实例3、用C语言给一个寄存器的bit7~bit17赋值937(其余位不受影响)
a &= ~(0x7ff<<7);//先将bit7~bit17全部清零,当然不能影响其他位。a |= (937<<7);//再将937写入bit7~bit17即可,当然不能影响其他位。

实例4、直接用宏来置位、复位(最右边为第1位)。
#define SET_NTH_BIT(x, n) (x | ((1U)<<(n-1)))#define CLEAR_NTH_BIT(x, n) (x & ~((1U)<<(n-1)))

二.中断

一.外部中断相关寄存器

1.定时器/计数器控制寄存器控制寄存器(TCON)
这里写图片描述
IT0:外部中断0触发方式控制位
当IT0=0时,为电平触发方式(低电平有效)
当IT0=1时,为边沿触发方式(下降沿有效)
IT1:外部中断1触发方式控制位
当IT1=0时,为电平触发方式(低电平有效)
当IT1=1时,为边沿触发方式(下降沿有效)

2.中断允许控制寄存器(IE)
这里写图片描述
EX0:外部中断0允许位;
EX1:外部中断1允许位;
EA :CPU中断允许(总允许)位。

二.外部中断的处理过程

1、设置中断触发方式,即IT0=1或0,IT1=1或0
2、开对应的外部中断,即EX0=1或EX1=1;
3、开总中断,即EA=1;
4、等待外部设备产生中断请求,即通过P3.2,P.3.3口连接外部设备产生中断
5、中断响应,执行中断服务函数

interrupt 0 指明是外部中断0;
interrupt 1 指明是定时器中断0;
interrupt 2 指明是外部中断1;
interrupt 3 指明是定时器中断1;
interrupt 4 指明是串行口中断;

1、IE中断允许寄存器

EA:EA=0时,所有中断禁止(即不产生中断);EA=1时,各中断的产生由个别的允许位决定
ET2:定时2溢出中断允许(8052用1允许, 0禁止)
ES:串行口中断允许(1允许, 0禁止)
ET1):定时1中断允许(1允许, 0禁止)
EX1:外中断INT1中断允许(1允许, 0禁止)
ET0:定时器0中断允许(1允许, 0禁止)
EX0:外部中断INT0的中断允许(1允许, 0禁止)

2、TCON定时器控制寄存器

TF1:定时器T1溢出标志,可由程序查询和清零,TF1也是中断请求源,当CPU响应T1中断时由硬件清零。
TF0:定时器T0溢出标志,可由程序查询和清零,TF0也是中断请求源,当CPU响应T0中断时由硬件清零。
TR1:T1充许计数控制位,为1时充许T1计数(定时)。
TR0:T0充许计数控制位,为1时充许T0计数(定时)。
IE1:外部中断1请示源(INT1,P3.3)标志。IE1=1,外部中断1正在向CPU请求中断,
当CPU响应该中断时由硬件清“0”IE1(边沿触发方式)。
IT1:外部中断源1触发方式控制位。IT1=0,外部中断1程控为电平触发方式,
当INT1(P3.3)输入低电平时,置位IE1。此位为1设置为电平触发,为0设置为下降沿触发。
IE0:外部中断0请示源(INT0,P3.2)标志。IE0=1,外部中断1正在向CPU请求中断,
当CPU响应该中断时由硬件清“0”IE0(边沿触发方式)。
IT0:外部中断源0触发方式控制位。IT0=0,外部中断1程控为电平触发方式,
当INT0(P3.2)输入低电平时,置位IE0。此位为1设置为电平触发,为0设置为下降沿触发。

3、TMOD定时器工作模式及方式寄存器

此寄存器高四位用于T1,低四位用于T0。
GATE :定时操作开关控制位,当GATE=1时,INT0或INT1引脚为高电平,同时TCON中的TR0或TR1控制位为1时,
计时/计数器0或1才开始工作。若GATE=0,则只要将TR0或TR1控制位设为1,计时/计数器0或1就开始工作。
C/T :定时器或计数器功能的选择位。C/T=1为计数器,通过外部引脚T0或T1输入计数脉冲。C/T=0时为定时器,
由内部系统时钟提供计时工作脉冲。
M1 M0:T0、T1工作模式选择位
M1 M0:0 0方式0,13位计数/计时器
M1 M0:0 1方式1,16位计数/计时器
M1 M0:1 0方式2,8位自动加载计数/计时器
M1 M0:1 1方式3,仅适用于T0,定时器0分为两个独立的8位定时器/计数器TH0及TL0,T1在方式3时停止工作

三.定时器

定时器作为计数器可以完成很多功能的实现(比如定时扫描按键时时,每2ms扫描一次按键的状态,再用静态变量 key1_sum进行时间上的处理)
通过定时器
所以总结一下IAP15F2K61S2的定时器:
3个16位的定时/计数器T0,T1,T2。核心部件是加法计数器(TH和TL),对输入脉冲进行计数。
T0/T1有四种工作方式,由TMOD中的M1,M2决定(一般常用工作方式一);T2工作方式固定为16位自动重装载初值方式。(定时器,串口波特率发生器,可编程时钟输出源)
一般常用的是工作方式1
详细的特殊功能寄存器以及方式0/1/2的实例,就直接转载了。(文中的方式排列跟我有点区别)

编写单片机定时器程序的步骤:

对TMOD赋值,以确定T0和T1的工作方式。
计算初值,并将初值写入TH0,TL0或TH1,TL1。
中断方式时,对IE赋值,开放中断。
使TR0或TR1置位,启动定时器/计数器定时或计数。

T0/工作方式0/12T
void Timer0Init(void)		//100微秒@12.000MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x9C;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	EA = 1;         //开总中断(自己添加)
	ET0 = 1;        //开定时器中断(自己添加)
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时(可以拿出去用)
}

void T0_time()  interrupt 1      
{
     //这里不需要认为加入重装初值的代码(自动重装载)
     num++;
}
	
void main()
{
    TIM0init(); 
    while(1)
    {
	  if(num==4000)     //如果到了4000,说明1秒时间到
      {
             num=0;     //标志位清0
	     led1=~led1;   //让发光管状态取反
	  }
    }
}

特别注意,STC软件IE寄存器是没有给的,所以在编写的时候,在适当的位置还要加上EA(总中断),ETX(定时器中断)打开
在这里插入图片描述

杂记

1.静态变量
①概念与定义:
“静态变量”这一术语有两个容易混淆的定义:
语言无关的通用定义:与程序有着相同生命周期的变量;
C族语言特有的定义:以static存储类声明的变量
②有时希望函数中的局部变量的值在函数调用结束后不消失而保留原值,即其占用的存储单元不释放,在下一次该函数调用时,该变量保留上一次函数调用结束时的值。这时就应该指定该局部变量为静态局部变量(static local variable)。
举例:对某些必须在调用之间保持局部变量的值的子程序而言,静态局部变量是特别重要的。如示例所示,利用静态变量计算1!+2!+3!+4!+…10!的值。

#include"stdio.h"
int f(int n)
{
	 static int y=1;
	 y=y*n;
	 return y; 
}
int main()
{
	 int i,s=0;
	 for(i=1;i<=10;i++)
	  s=s+f(i); 
	 printf("%d",s);
	 return 0;
}

在该代码中,我们通过在 f() 函数里声明一个静态局部变量 y来储存上一次循环调用时y的结果。因为静态局部变量是在编译时赋初值的,且只赋初值一次,在程序运行时它已有初值。以后在每次调用函数时就不再重新赋初值,而是保留上次函数调用结束时的值。这样,f() 函数每次被调用的时候,静态局部变量 y就会保持上一次调用的值,然后再执行运算,这样就实现了数乘和功能。同时,它又避免了使用全局变量。(举例转载)
2.头文件的引用


#ifndef __HEAD_H__
#define __HEAD_H__
 
 
int add(int,int,int);
 
 
#end if

加了头文件#include <STC15F2K60S2.H> ,就可以不用用sfr寻址了,直接sbit PX^X就行了。自己编写的头文件注意用上面的格式进行编写,把调用的函数名放进去就行。

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值