资讯详情

C_单片机, 硬件

catalog

  • 51单片机
    • 串口
    • 寄存器
    • 定时器
    • 138译码器
    • 电平
    • LED数码管
    • 引脚IO口
    • 引脚冲突
    • 独立按键
    • 矩阵键盘
  • Keil
  • 单片机
  • 电脑硬件
    • 总线
    • cpu操作数据
      • cpu读数据
      • cpu写数据
    • 存储器
      • 显存
      • 磁盘
      • 虚拟内存
    • 寄存器
  • 单片机
  • MSC51
    • 总线
    • CPU
    • IO口, 引脚
    • T/C
    • ROM
    • RAM
    • 晶振
    • 复位
    • 电容
    • LED
  • C-51语言
    • for循环
    • 数据类型
    • 函数内static变量

51单片机

串口

自带单片机UART: universal asynchronous receiver transmitter 通用异步接收器, 来实现 (串口通信)

通过(串口通信), 可实现: (单片机和单片机), (单片机和电脑), 通信(单片机及各模块)

串口的标准接口为: DB9 (9针, 上4下5), 现在计算机没有这样的接口了。 VGAvideo graphics array 视频图形阵列的接口是: DB15 (15针, 上、中、下各5个) 与图像视频有关 是这个; 比如, 主机与投影仪连接, 连接主机和显示屏, 是VGA接口; 而串口DB9, 仅用于传输数据


简单的双向串口通信, 有2条通信线 (TXD, RXD), 1个VCC, 1个GND TXD: transmit exchange data 发送; RXD: receive exchange data接收 若为单向通信接口, 一条通信线可以

串口0: VCC_0, GND_0, TXD_0, RXD_0 串口1: VCC_1, GND_1, TXD_1, RXD_1  VCC_0 --- VCC_1 GND_0 --- GND_1 TXD_0 --- RXD_1   ' 交叉 ' RXD_0 --- TXD_1 

串口常用的 (电平标准):

  • TTL电平: 5V为1, 0V为0
  • RS232电平: {-3到-15V} 为1, { 3到 15} 为0 注意, 负值 为 1
  • RS485电平: d 两线电压差 d为{ 2到 6}为1, d为{-2到-6}为0 差分

对于(TTL和RS232), 都是一条线, 看他和GND(恒为0V) 对比电压; 而对于(RS485), 他是两条线, 不需要GND, 看两条线的差分值


(TTL和RS232)电平, 最多是10米; 不能太长; 而(RS485电平) 可传输1000米, 这就是 (差分电平)优势


常见(通信接口):

(全双工: 同一时刻, 可以发送 可以接收) (单双工: 同一时刻, 要么发送 要么接收, 二选一; 即在一段时间内, 即可发送 也可接收) (单工: 要么发送 要么接收, 二选一)

同步、异步问题:

,比如, (A发送1 0, 他对应的模拟信号是: --__, A的频率是1s) ,如果(B以1/2s接收频率, 他会得到: 1 1 0 0; ), 所以, 这个频率, 要约定好; 这是(同步异步)的问题 (异步: 双方同意相同的频率) (同步: 打开另一个时钟线, 规定频率, 双方不必考虑频率)

(总线): 连接多个设备, 实现设备间的通信

寄存器

单片机, 通过 配置寄存器, 来控制 连接内线

寄存器是 连接 软硬件中介;

寄存器就是 一个特殊的 RAM存储器; (他可以存储 和 读取 数据), 每个寄存器都连接在一起 (一根导线), 即控制 电路连接

寄存器相当于: 一个机器的 操作按钮

定时器

定时器 是 (单片机) 的 内部资源, 不属于 (由IO口控外设)

原理: (定时器) -> 时钟脉冲 -> (计数器) -> 产生中断 -> (中断系统)

计数器为16位, 即最大是65535

定时器, 每个(时钟脉冲), 计数器就 = 1


晶振是12Mhz (hz是: 赫兹; 是频率单位; 1hz表示: 1s执行一次操作; x hz表示: 1sx操作; 1Mhz: 1s执行1e6次操作) 51单片机采用12分频, 12Mhz / 12 = 1Mhz; 1Mhz即: 1s 执行 1e6次操作; 即每个1e-6 = 1us时间, 执行一次操作

即, 每1us, 会产生脉冲; 即, 计数器 就会 = 1

此时, 假如我们想: (每隔50ms, 触发一次中断事件), 50ms / 1us = 50000, 即50000个计数 我们知道, 每1us, 计数就会 =1; 计数65535后, 就会 触发中断 所以, 我们的计数器, 要设置初值为: 65535 - 50000 = 15535


void Timer0_Routine() interrupt 1{ 
        
//< interrupt function
	static unsigned int count = 0;
	++ count;
	{ 
         //< 重置计数器
		TH0 = 15535 / 256;
		TL0 = 15535 % 256;
	}
	
	if( count >= 20){ 
         //< 20 * 50ms = 1s
		//* execute
		count = 0;
	}
}

void main(){ 
        
	Timer0_init();	
	while( 1){ 
        
	}
}
static void Timer0_init(){ 
        
	{ 
         //< 定时器模式
		TMOD &= 0xF0;
		TMOD |= 0x01;
	}
	{ 
         //< 
		TH0 = 15535 / 256;
		TL0 = 15535 % 256;
	}
	{ 
         //< ÅäÖÃ
		TF0 = 0;
		TR0 = 1;
		ET0 = 1;
		EA = 1;
		PT0 = 0;
	}
}

138译码器

输入有3个IO口, 输出有8个LED接口

根据你输入的这3个IO口a b c, 转换为 10进制a*4 + b*2 + c, 这个数 即{0 -7}范围的, 就对应 输出

即, 根据你的abc输入, 就可以选中 8个LED接口的 一个

好处: 减少IO口, 通过3个IO口, 就可以 选中8个接口中的一个

电平

单片机是: (高电平的 驱动能力弱) (低电平的 驱动能力强)

所以, LED/按钮等 都是采用 (低电平) 点亮的方式; 即正常是1(高电平), 0(低电平)是触发状态


(共阴极方式)的 数码管, 在输入正极端, 会加 (双向数据缓冲器), (缓冲器: 增大驱动能力)

如果IO口直接 接数码管, 则: 单片机输出的数据, 就直接当做 驱动的数据 此时, IO口 通过(缓冲器) 到 数码管, 则: 通过缓冲器, (缓冲器里有VCC) 吸取能量, 然后再输出到 数码管里; 数码管就比较亮

LED数码管

一个数码管, 由8个LED封装在一起, 组成8的形状,

一个LED, 图形是<三角形; 箭头的指向, 是阴极, 即(从阳极到阴极)

这8个LED, 要么8个箭头都指向一个引脚(共阴极连接方式), 否则, 8个箭头指向8个引脚, 一个引脚连接8个LED (共阳极方式)

一个数码管模块, 有10个引脚; 比如以(共阳极方式)为例, (3 和 8)号引脚 连接8个LED的阳极; 8个LED的阴极 连接 (其他8个引脚)


4位一体的数码管, (4个数码管, 共用同一个模块), 外接12个IO口

以(共阴极)为例: (4个数码管L0{0-7} L1{0-7} …) 外接IO口的{0-7}, 同时控制 L{0-3}{0-7}; 即, 一个IO口(比如0号), 他同时控制L{0-3}0, 即同时控制4个LED 每个数码管的阴极, 连接一个IO口; 即L0数码管(8个LED), 同时连接1个IO口

一共是8 + 4个IO口;

可以发现, 我们只能让(1个数码管) 显示数字!!! 不可能让4个数码管显示不同的数据; 因为, 如果让4个数码管展示不同数字, (第1, 外接的4个阴极IO口 必须都是0 这样4个数码管才能工作) (第2, 具体你要展示什么数, 通过8个IO来控制;) 这样, 所有4个数码管, 展示的数字 都是相同的;

如果要展示:1 2 3 4, 需要用到动态数码管展示技术 (每次展示1个数码管, 然后快速的去展示第2个数码管, …);

首先讲, 如何让一个数码管展示 (通过8个IO口, 控制要展示的数字) (让该数码管的阴极的IO口 为0, 其他3个数码管的阴极IO口为1)

这样做的好处: (1, 需要的IO口, 很少; 否则, 你需要8*4 + 1个IO口)

也有(8位一体)的, 即需要8 + 8个IO口


void Show_LED_number( int _id, int _num){ 
        
	if( _id & 1){ 
         P2_2 = 1;}
	else{ 
         P2_2 = 0;}
	if( _id & 2){ 
         P2_3 = 1;}
	else{ 
         P2_3 = 0;}
	if( _id & 4){ 
         P2_4 = 1;}
	else{ 
         P2_4 = 0;}
	
	if( 0){ 
        }
	else if( _num == 0){ 
         P0 = 0x3F;}
	else if( _num == 1){ 
         P0 = 0x06;}
	else if( _num == 2){ 
         P0 = 0x5B;}
	else if( _num == 3){ 
         P0 = 0x4F;}
	else if( _num == 4){ 
         P0 = 0x66;}
	else if( _num == 5){ 
         P0 = 0x6D;}
	else if( _num == 6){ 
         P0 = 0x7D;}
	else if( _num == 7){ 
         P0 = 0x07;}
	else if( _num == 8){ 
         P0 = 0x7F;}
	else if( _num == 9){ 
         P0 = 0x6F;}
	
	Delay_milliSecond( 1);
	P0 = 0;
}

(第一步), 位选, 即选中一个数码管 8位一体, 选中其中的一个 (第二步), 段选, 写数字; …这里有一个(影子问题), 当我们(第二步)执行完了, 此时(第x0个数码管, 展示了x1数字), 然后接下来, 马上进行第x2个数码管, 展示x3数字 ,即动态刷新; 但是, 当执行完选中第x2个数码管后, 此时, 还是x1数字, 所以, 此时会有第x2个数码管, 展示x1数字 ,不过这会很快被x3数字刷新掉; 但 仍然会 留下一下影子; ,所以, 这里要(消除 影子), 即, 在展示完数字后,要置为0 (当然不能太快, 等展示出来数字后, 再置0), 这样, 下一次(位选)后, 全是0, 即没有LED点亮


这种通过单片机, 不停的 刷新, 来展示数码管; 有缺点: 大量的占用CPU时间 有(专门的 驱动数码管的芯片), 我们直接调用接口即可

引脚IO口

单片机刚上电时, 所有IO口 都是 高电平

比如, 按键: 默认是不按下的, 即(高电平);


单片机的(IO口)是: 弱上拉模型 (准双向口), 即(既可以输入, 也可以输出 )

引脚冲突

(LED模块), (数码管模块), (LCD屏模块), 都存在 引脚IO口冲突; 你只能选择使用1个模块

独立按键

轻触开关: 按下时接通, 松开后断开

P3_0 ----> [button] ----> GND (由于单片机默认是 高电平), 即, 初始状态(未按下), 是:1 -> [] -> 0 按下后, 会变成: 0 -> [] ->0

轻触开关 不分正负极, 这非常重要, 按钮是两端都是0, 表示 (按下)

int Get_pressed_button_number(){ 
        
	if( 0){ 
        }
	else if( P3_1 == 0){ 
         return 0;}
	else if( P3_0 == 0){ 
         return 1;}
	else if( P3_2 == 0){ 
         return 2;}
	else if( P3_3 == 0){ 
         return 3;}
	return -1;
}	

矩阵键盘

为了节省IO口的占用, 采用矩阵键盘4 * 4的方式; 使用4个行 + 4个列 = 8个IO口; 采用(按行扫描)的方式来读取状态 否则, 他需要(16 + 11表示: 一个输入/输出IO口)个 IO口

键盘: x0, x1, x2, ..., x15 4个输入 IO口, 一个IO口 同时连接4个键盘{ (x0,x1,x2,x3}, {x4,x5,x6,x7}, ...} 4个输出 IO口, 一个IO口 同时连接4个键盘

在(独立按键)那, 我们知道, (轻触开关不分 正负极!!!), 当两端都是0 表示 按下; 而且, 那里 是 一端为GND, 即恒为0; 所以, 只需判断另一端即可 但是, 这里不同的是: 这里两端都是 (IO口)!!! 所以, 这里, 你就需要自己去测试!!! 即, (让他的一端) 先给置为0 手动的去赋值IO口, 然后, 你去检测他的 另一端的IO口, 看是否为0

此时有2种方式:

  • 按行扫描; (4个行 即4个IO口, 表示所有按键的一端)
    for( row = 0; row < 4; ++row){ 
              
    	将row对应的IO口, 置为0; 其他row的IO口, 置为1;
    	for( col = 0; col < 4; ++col){ 
              
    		if( col对应的IO口 == 0){ 
              
    			// [row, col] 按下了
    		}
    	}
    }
    
    比如, (行对应的 IO口P1 _ {4-7}, 你需要不停的, 给这4个IO口, 赋值为: [0111 -> 1011 -> 1101 -> 1110] 一直赋值), 然后检测列
  • 按列扫描; 即对列进行循环赋值, 然后检测行

包括我们的屏幕, 也是 采用(扫描节省IO口)方式; 以1920 * 1028的分辨率为例, 他的每一个单元 即一个(像素点), 按理说 他需要: 1920 * 1080 + 1(一个输入/输出口) 个IO口, 来控制每个像素点; 这是非常非常多的 实际上, 他也是采用(矩阵扫描)的方式, 1920 + 1080个IO口; 这个扫描, 是由显卡负责的


Keil

由于stc是国产的, 在选择cpu类型时, 选择at89c52

optionoutput里, 勾选上 create HEX file

烧录软件: 不要使用(STC-ISP), 使用 (普中科技软件)!!!

单片机

在我们的PC里, (CPU, RAM, ROM, I/O这些), 都是单独的芯片, 将这些都集成起来, 安装到一个(主板)上, 就是我们的主板

而单片机MCU: micro control unit, 是将 (CPU, RAM, ROM, I/O这些), 都继承在一个芯片


单片机有: (8位的: 51单片机), (32位的: STM32)

(芯片), 由2部分组成: (内核) 和 (外设); 类似于: CPU 和 {内存,...} 的关系

ARM公司, 只设计 (内核), 他不生产(芯片);

芯片厂商ST公司 (STM芯片), 都是基于这个ARM的 (内核), 来设计 (外设)


(内核) 和 (外设), 是由2个公司设计的; 他们之间, 通过 (总线) 通信

电脑硬件

总线

cpu 与 外部器件(外部器件又称:芯片)需要进行交互
他们之间,就是通过“总线”(本质是导线)进行连接的

cpu对数据的操作

cpu与外部器件(外部器件又称:芯片)的交互,必须知道以下信息: 
1,地址信息(需要知道:内存/硬盘/显卡/网卡的 地址)
2,控制信息(读取/写入 数据)
3,数据信息(数据的内容)
 ' 这3种信息,对应到物理总线上: 地址总线/控制总线/数据总线 '

(cpu) 通过 <地址/控制/数据 3种总线> 与 (内存) 进行数据通信
' 这里的“内存”,并不单指内存条,还包括:显卡的内存、网卡的内存 '

cpu读数据

cpu 从 “内存:不单指内存条” 读取数据
1, cpu通过 地址总线,发送一个地址Tar
2, cpu通过 控制总线,发送“读指令”
3, cpu通过 数据总线,得到“Tar地址”的数据

cpu写数据

cpu 往 “内存:不单指内存条” 写入数据
1, cpu通过 地址总线,发送一个地址Tar
2, cpu通过 控制总线,发送“写指令”
3, cpu通过 数据总线,发送数据Data(Tar地址的数据,会被更新为Data)

存储器

其实计算机的各个部件,都有“属于他自己“的存储器,比如显卡的显存

存储器是划分为了多个“存储单位”
比如,一个存储器 他有128个存储单元

广义上的“内存”,并不单指内存条,还包括:显卡的内存、网卡的内存

显存

比如显存: 	一个显卡是无法单独运行的,显卡里面有个内存,叫做显存
   你把数据存到“显存”里面,显卡里面有个叫做gpu的处理器
   会把显存里的数据,映射到屏幕上(gpu的速度,要比cpu还快)

磁盘

磁盘是不同与内存的, 磁盘里的数据/程序,必须要放到内存里,才能被cpu使用

cpu   ->   内存   ->   磁盘/光盘/硬盘
比如磁盘里的“xx游戏”, 运行时,他需要先 “加载到内存”
 这样,cpu才能和内存进行交互数据,这个游戏才能运行起来

虚拟内存

当内存不够时,会增加一个“虚拟内存”
虚拟内存:   将一些不经常用到的内存,临时放到“硬盘”里
   需要的时候,再将其从“硬盘” 放到内存里。

寄存器

寄存器:   嵌入到cpu内部的内存,即cpu内部的存储器
	cpu内有很多寄存器,比如ax、bx 这些都是寄存器的名称

有的寄存器存储的是:数据
有的寄存器存储的是:指令

单片机

最以前, 他叫做:  单板机 
将'cpu,存储器,io设备(小键盘/LED显示器)'等,装在一块印刷电路板上

后来,演变为 单片机(单芯片微型计算机)

单片机使用的是 TTL电平(+5V为 高电平)
单片机是 从计算机 通过'串口' 把程序下载到 单片机里面
   这里的串口, 是使用的RS232串口 (他的高电压是-12V)
' 即,计算机 与 单片机 通信时, 两者的 电平标准不同!! { 
        +5V 和 -12V 无法通信}'
'    故, 需要使用  “电平转换芯片”(max232)  即,将+5V 转换为-> -12V '

单片机运行起来的 '必要条件':
	1,电源
	2,晶振(就像人的心跳,需要不停的跳动)
	3,复位电路(单片机在上电时,必须进行一次复位)

对单片机任意IO口的 操作:
  ' MSC51有4个8位IO口,即有32个位 '
  1, 你可以, 输出该位的 电平高低
  2, 你可以, 输入IO口的电平
	

MSC51

MSC51是 Intel公司推出的 一系列单片机的总称,有“8031, 8051 ”等型号
其中,最经典的是 8051型号。  所以,习惯用8051 来代指 MSC51单片机
  8位cpu、4K的rom、128的ram、4个8位并口、1个全双工串行口
  寻址范围是 64K

总线

bus总线:   计算机各个部件之间传送信息的公共通道
分为: 内部总线  和  外部总线
	外部总线,分为:    数据总线Data bus(DB)、地址总线AB、控制总线CB

CPU

由:  '运算逻辑 、 控制逻辑 、 中断系统 、 寄存器' 组成

IO口, 引脚

引脚是分8个为一个组, P0、P1、P2、P3组(称为: 四个8bit 并行口)
 每组有8个,即P0.0  P0.1  P0.2  P0.3  ...  P0.7
 这个8,就对应CPU的位数(因为CPU的位数是8!!!) 

T/C

timer计时器 和 counter计数器

ROM

rom:  read-only mem    只读
	只能读出,预先以存储好了的数据
	(即,'硬盘'的概念:  数据保存在其中,不会丢失)
	(但也不完全是硬盘,因为硬盘是可读可写的)

RAM

ram:  random access mem   随机存储
	断电丢失数据,用于存储 '短时间内所运行的程序'
	(即,'内存'的概念: 负责程序的运行,数据交换)
	(在计算机运行的过程中,一些随机的变量 可以实时的调用)

晶振

程序是一条一条命令来执行的。
命令A -> 命令B
比如,现在是在“命令A”  如果没有晶振,就会一直在“命令A”
晶振的作用是:  给单片机提供“时钟”,驱动它,一步一步的往下走 

复位

reset复位RST, 复位电路:  让程序 从“最开头”开始执行

电容

作用是“滤波”,电源VCC可能会不稳定,就像是“水流” 时快时慢
电容: 就像一个“池子”,先预先存储一些水(电荷),然后再从池子里 放出去
这样, 放出去的 就比较稳定

符号是 =, 他的英文capacitor 容量, 简写cc

LED

开发板会默认带有8个LED,称为LED模块,  LED: light emit  diode 发光二极管
 (正极VCC) -> [限流电阻] -> [L-8个LED-R] -> P2.[0-8]引脚
  限流电阻的作用是:  VCC的电压是5V,电流比较大; 串联一个电阻后,电流就会变小
  此时, LED的L端 已经是“正电”了; 则LED的R端:  接负电,则灯亮; 接正电,灯不会亮
  ' 此时,问题转换为:  控制P2.[0-8]引脚 输出 高(+5V) 还是 低(0V) 电平的问题。 '
   要深入这个问题,就需要先理解寄存器的功能
   单片机内部:[ cpu -- 寄存器 -- 驱动器 -- 引脚 ]
   寄存器,其实就是一种存储器,他里面有8个bit,这个8个bit就对应外部的8个引脚
     比如,这个寄存器叫做P2  那么他对应的8个引脚 就是P2.[0-7]
     8个bit,通过8个驱动器,连接8个引脚。   驱动器:  增大电流
   cpu,通过你写的程序 直接的访问这个寄存器,即直接往寄存器里 写值
   比如,往P2寄存器的[0]位,写1  ->   则,他会通过驱动器,最终给P2.0引脚 提供高电平+5V
       0号LED 左右都是正, 所以他不会亮。   只有当他是0,即提供低电平,灯才会亮。
  ' 即,cpu通过 控制寄存器里的值, 来控制 外部的硬件电路 '

C-51语言

C-51语言,在C语言的基础上,拓展了新的功能:
1, 新添了一些 '基础数据类型'
	sfr: 特殊功能寄存器
	sbit: 特殊功能位
	sfr16: srf的16位数据
	bit:  位变量
 sbit bit = PSW^2    'PSW是单片机内的一个寄存器,一个寄存器是8位'
 ' ^2的意思是,该寄存器的第2位;  即,你直接操作bit 就是在操作寄存器 '

for循环

for( int i = 0; i < 10; ++i){} 这是错的!!!

必须是: int i; for( i = 0; i < 10; ++i){}

数据类型

注意, int 是2字节的+- 32767!!! int i; for( i = 0; i < 100000; ++i){} 这就死循环了!!!

long是 4字节

函数内static变量

static变量, 必须写在 (函数最开头)!!! 他的前面, 不可以有非static

以下代码是错的; 必须让static int b;在前面

void Func(){ 
        
	int a;
	static int b;
}

标签: 国产mcs连接器8x4电阻器定时器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台