假定单片机时钟频率的最大值为1000kHz,此时周期为1us,说明单片机能捕捉到比1us长的数据,在1us内来的若干数据就捕捉不到了,因为单片机最快1us翻转一次,周期肯定比1us大,所以,置高后立马置低的这个信号,单片机是可以捕捉到的。学习过程中没怎么记过笔记,想复习的时候发现只能挨行看代码,老师讲的东西当时好像看着挺简单能记住,其实过两天也忘得干干净净,现已学到6-2,…

本文最初发布于 CSDN,现迁移至本站并做格式整理。内容保留原始观点与发布时间。

background

计算机研一自学51单片机笔记
时间:24/3/5 —— 24/4/8
学习过程中没怎么记过笔记,想复习的时候发现只能挨行看代码,老师讲的东西当时好像看着挺简单能记住,其实过两天也忘得干干净净,现已学到6-2,特开此贴记录一下往后的课堂笔记,供个人复习使用,也希望能对各位网友有一定帮助~
还剩了个尾巴学32去了,后面就不更新啦~

7-1 之前

  • 数码管:分共阴和共阳,占用CPU时间需要一直扫描
  • 74LS138:3位译码到8位,低电平有效
  • 弱上拉,强下拉:高位点亮的电流有限,但是低位点亮可以吸引更多的电流,亮度比前者大,P1、P2、P3都是强上拉
  • 电容单位: pF、nF、 μ F、mF、F  \text{pF、} \text{nF、}\mu\text{F、} \text{mF、} \text{F } pF、nF、μF、mF、F  由小到大,数量级 1 0 − 3 10^{-3} 10−3
  • 数码管消影:
    位选 → \rightarrow → 段选 → \rightarrow → 位选 → \rightarrow → 段选 → \rightarrow → 位选 → \rightarrow → 段选 → … \rightarrow \dots →…
    位选下一位的瞬间 ,下一位的段信号还没有到,此时收到的还是上一位的信号,so,123的话2会有1的残影,3会有2的残影,1会有3的残影

7-1、7-2 定时器 中断

相关寄存器:

  • TCON:Timer Control的简写,可位寻址,每一位可单独赋值
    TF中断溢出标志位,给1时产生中断, TR定时器是否开启,TF0,TR0代表第一个计/定 时器
  • TMOD:Timer Model,M1M0控制模式选择, C / T ‾ C/ \overline{T} C/T清零用作定时器,置1用作计数器,不可位寻址,每一位不可单独赋值
    TMOD = 0x01; \\ 定时器1全设为0, 定时器2GATE和CT都为0,模式为01

8-1、8-2 串口通信

可实现两个设备之间的相互通信
51单片机内部自带UART(通用异步收发器),电脑用USB转串口
文章配图
简单的是TXD(transmit eXchange data)、RXD两根,复杂的再多加线用于流控制
上图可以一发多收

电压与数据的对应关系为电平标准:

  • 单片机使用TTL电平,+5V表示1,0V表示0
  • RS232和上面差不多只是区间不一样,一般用在高电压传输,这两个只能传输十多米
  • RS485(差分信号)电平,两个导线的压差+2~6V表示1,加负号就是0,CAN总线,USB都是使用差分信号,能传输1km+
    文章配图
  • 全双工:AB可以在同一时刻相互传输数据
  • 半双工:AB可以相互传输数据,但是必须分时复用一根数据线
  • 单工:单向A → \rightarrow → B
  • 异步:双方约定各自的通信速率
  • 同步:靠一根时钟线约定通信速率(波特率),上图SCL、SCLK
  • 总线:连接各设备的数据传输线路,线的总路,能挂载多个设备
  • SPI:在时钟的上升沿写入数据,下降沿读出数据
    文章配图
  • 通过控制定时器1(TH1、TL1)来确定收发器的采样时间
  • 接受和发送时会产生中断,发送时产生的TI中断不需要干什么,接收时产生的RI中断用于读取数据
    文章配图
  • 之前定时器的中断是进入T0,这次的中断是进入RX、TX,这两个中断占用的同一个通道
  • ES,enable serial; PS 串口优先级
    文章配图
  • 其中PCON是电源相关寄存器,用不满8位,空下的就留给串口用了
  • 这个表主要是看每个寄存器的特定位置,比如TI、RI、EA、ES这种需要编程配置的
  • TI :发送中断请求标志位。在方式0,当串行发送数据第8位结束时,由内部硬件自动置位,即 T=1,向主机请求中断,响应中断后必须用软件复位,即 T0。在其他方式中,则在停止位开始发送时由内部硬件置位,必须用软件复位。也就是说发送完了必须写一句置零的代码。 RI也是一样的
  • SMOD控制波特率是否加倍的
1
2
3
void UART_Routine() interrupt 4{
pass;// 函数后面跟了后缀,产生中断时就会自动跳入对应的中断函数,数字4代表了串口中断
}

数据显示模式:

  • HEX/十六进制/二进制:以原始数据的形式显示
  • 文本/字符模式:以原始数据编码(ASCII码)后的形式显示

波特率计算

  • 0xf3 -> 243, 256-243 = 13, 也就是说每记13个数就溢出一次
  • 12M的晶振在12T的模式下,每1us记一次数,也就是说上面每13us就溢出一次
  • 溢出率 = 1/13us = 0.07692MHz,波特率 = 0.07692MHz/16 = 4807.69Hz

9-1、9-2 LED点阵屏

  • 74HC595可以同时扩展8位,三根线控制串行输入,并行输出,常用于IO口扩展,74LS138每次只能选中其中的一位
  • sfr 声明寄存器中的地址
  • sbit 声明寄存器中的某一位
  • 可位寻址/不可位寻址:在单片机系统中,操作任意寄存器或者一位的数据时,必须给出其物理地址,又因为一个寄存器里有8位,所以位的数量是寄存器数量的8倍,对不可位寻址的存器,若要只操作其中一位而不影响其它位时,可用“&=”、““|=”的方法进行位操作
    • &= 用于清零,因为任何数和0与之后都是0
    • |= 用于置1, 因为任何数和1或之后都是1
    • ^= 用于取反
  • sbit RCLK = P3^5 P3是0xB0,异或5就是0xB5
  • SER = Byte&0x80; 运算符两边的Byte和0x80都是8位十六进制数,但是SER只能接收一位, Byte&0x80是将Byte的最高位和1进行与操作,SER接收的数据非零即1,当 Byte&0x80的结果是非零的0x10,则SER被赋值1,当 Byte&0x80的结果是0x00,则SER被赋值0,这个结果之和Byte的最高位有关系
  • #define MATRIX_LED_PORT P0这样做是因为当换了个板子可能就不是P0控制相应的功能,这样直接修改PORT后对应的端口就ok
  • unsigned char code Ani[] 这样可以把数据存在flash里面,不加code数据就存在RAM里面,在flash里面的数据不能更改

10-1、10-2 DS1302时钟

文章配图

  • 还有DS3231,内部自带晶振,集成度高,贵
  • DS12C887,自带电池不需要外接
  • 拿到芯片先看功能,再看DataSheet
    文章配图
  • 晶振:石英晶体振荡器
  • CE:chip enable
    文章配图
  • SCLK:在时钟的上升沿写入数据,下降沿读出数据
1
2
3
4
5
6
7
8
9
10
11
DS1302_IO = Command&0x01; //取命令字的第0位
DS1302_IO = Command&0x02; //取命令字的第1位
DS1302_IO = Command&0x04; //取命令字的第2位
DS1302_IO = Command&0x08; //取命令字的第3位
DS1302_IO = Command&0x10; //取命令字的第4位

for(i=0; i<8; i++){
DS1302_IO = Command&(0x01<<i); //取命令字的第i位 和上面等价
DS1302_SCLK = 1;
DS1302_SCLK = 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
unsigned char DS1302_ReadByte(unsigned char Command){
unsigned char i,Data = 0x00; // 这个定义必须在函数的第一行 不然报错!!
DS1302_CE = 1;

for(i=0; i<8; i++){
DS1302_IO = Command&(0x01<<i); // 写入命令字
DS1302_SCLK = 0;
DS1302_SCLK = 1; // 上升沿写一个bit
}

for(i=0; i<8; i++){
DS1302_SCLK = 1; //根据时序图保持高电平
DS1302_SCLK = 0; //给下降沿时 数据自动到IO线上
if(DS1302_IO) Data = Data|(0x01<<i); // Data|=(0x01<<i);
}
DS1302_CE = 0;
return Data;
}

BCD码(Binary Coded Decimal),用4位二进制数来表示1位十进制数

  • 0001 0011表示13,1000 0101表示85,0001 1010不合法
  • 在十六进制中的体现:0x13表示13,0x85表示85,0x1A不合法
  • BCD码转十进制:DEC=BCD/16*10+BCD%16;(2位BCD) 除以16提取高四位,再×10转化为十位
  • 十进制转BCD码:BCD=DEC/10*16+DEC%10;(2位BCD)
  • LCD_ShowNum(2,1,Sec/16*10+Sec%16,3);等价于LCD_ShowHexNum(2, 1, Sec, 3);
1
2
Select%=6;
if(Select>6) Select=0; // 这两句话是等价的
  • fFlage=!fFlage;是逻辑取反 fFlage=~fFlage;是按位取反

11-1、11-2 蜂鸣器

  • 定时器就是隔一段时间(周期)进入一次相应的中断程序,板子上的是无源蜂鸣器,需要外部给频率来使蜂鸣器发声,通过控制定时器的溢出周期(TL0,TH0),来控制蜂鸣器接收的频率
  • 蜂鸣器接的是P3_5,所以在定时器函数内使其翻转充当震荡源
  • 一个方波周期内,信号会翻转两次,如果1ms翻转一次,周期就为2ms,频率为1s/2ms=500Hz,此时蜂鸣器发出500Hz的声音
  • 机器频率是震荡频率的1/12,晶振的震荡频率为12MHz,所以机器频率为1MHz,一个机器周期就是1us, 也就是每1us定时器的计数值+1,一直加到65535就溢出,溢出就会触发中断函数
  • 联想前面学过的,假定需要500us溢出一次,TH0和TL0就要设置为65535-500,这样在此基础上计数器加500次即500us就溢出跳转到相应的中断函数中
  • 在这里,假定需要蜂鸣器工作的频率为500Hz,蜂鸣器工作的周期时间就为1s/500Hz=2ms=2000us,一个周期内信号会翻转两次,所以翻转一次的时间2000us/2=1000us,所以需要每1000us进入一次中断函数进行翻转,即每1000us计数器需要溢出一次 ,此时TH0和TL0 = 65536-1000

12-1、12-2 AT24C02(I2C总线)

文章配图

  • RAM: Random Access Memory,掉电丢失,快

  • ROM: Read Only Memory,掉电不丢失,慢

  • SRAM,静态,类似触发器,速度最快,cpu里面用这个

  • DRAM,电容存储,容易漏电,每隔一段时间扫描动态刷新补电,运行内存,内存条

  • Mask ROM,出厂是什么内容就是什么内容,只能读不能写

  • PROM,可编程ROM,只能写入一次

  • EPROM,可擦除可编程ROM,但是需要紫外线照射三十分钟才能擦除

  • E2PROM,24C02就是这种,2506字节,5V低压电,几毫秒就能擦出

  • 早期AB盘,就是留给软盘的

  • 假定单片机时钟频率的最大值为1000kHz,此时周期为1us,说明单片机能捕捉到比1us长的数据,在1us内来的若干数据就捕捉不到了,因为单片机最快1us翻转一次,周期肯定比1us大,所以,置高后立马置低的这个信号,单片机是可以捕捉到的

  • AT24C02_ReadByte(1)<<8;虽然AT24C02_ReadByte(1)只有8位,但是运算时存在32位中,所以在此基础上左移8位并不是8个0

1
2
3
4
Nixie(i, Nixie_Buf[i]);
i++; // 显式自增,避免歧义

Nixie(i,Nixie_Buf[i++]); //Dangerous!!!
  • 上面这两个不一定是等价的,因为函数参数的计算顺序未知,当i=1时,Nixie(i,Nixie_Buf[i++])若先计算第一个参数再计算第二个参数则等价于Nixie(1,Nixie_Buf[1]),然后i++变成2;若先计算第二个参数再计算第一个参数则等价于Nixie(2,Nixie_Buf[1]),因为在计算第二个参数的时候i++就已经执行了

13-1、13-2 DS18B20温度传感器

文章配图

  • 寄生供电:只需要gnd和数据线就可以实现功能
  • VCC是表示电路的意思,指的是接入电路;VDD表示器件的意思,指的是器件内部的工作电压;VSS表示公共连接段的意思,指的是公共接地端电压的意思
  • 这个跟三极管和MOS管有关,三极管有BCE三个脚,MOS有GDS三个脚,一般C和D是接正极的,E和S是接地的,所以VCC和VDD表示接电源正极,VSS和VEE表示接地
  • 为什么要接上拉电阻??重新听一遍!!!!!!!
  • EEPROM读写的时候属于耗电操作,必须给强上拉