51单片机学习笔记

Posted 黑胡子大叔的小屋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51单片机学习笔记相关的知识,希望对你有一定的参考价值。

51单片机学习笔记

DS18B20温度传感器

常见温度传感器有数字温度传感器,还有模拟温度传感器。DS18B20为数字传感器,通信接口1-Wire(单总线),可寄生供电,可设置阈值,可设置精度。
单总线的接线有三条(GND、VCC、DQ),异步半双工,寄生供电时可以去除VCC线路。


电路规范:

  • DQ需要配置成开漏输出模式
  • DQ添加一个上拉电阻,组织一般为4.7KΩ
  • 若从机采用寄生供电,主机还需要配一个强上拉输出电路

前两条同IIC


1-Wire时序结构

初始化

主机将总线拉低至少480us,然后释放总线,等待15 ~ 60us后,存在的从机会拉低总线60 ~ 240us响应主机,之后从机释放总线;分为两个部分:复位和响应。

/**
  * @brief  主机将总线拉低至少480us,然后释放总线,等待15 ~ 60us后,
						存在的从机会拉低总线60 ~ 240us响应主机,之后从机释放总线;
						分为两个部分:复位和响应。
  * @param  
  * @retval 
  */
unsigned char OneWire_Init()

	unsigned char i;
	unsigned char AckBit;
	
	OneWire_DQ = 1;
	OneWire_DQ = 0;										// 拉低总线

	i = 247;
	while (--i);											// Delay 500us
	
	OneWire_DQ = 1;										// 释放总线
	
	i = 32;
	while (--i);											// Delay 70us
	
	AckBit = OneWire_DQ;							// 获取从机响应
	
	i = 247;
	while (--i);											// Delay 500us
	
	return AckBit;

发送一位

主机将总线拉低60 ~ 120us,释放总线,表示发送0;主机将总线拉低1 ~14us,释放总线,表示发送1。从机将在主机拉低30us后读取电平,整个时间片应该大于60us。


/**
  * @brief  主机将总线拉低60 ~ 120us,释放总线,表示发送0;
			主机将总线拉低1 ~ 14us,释放总线,表示发送1。
			从机将在主机拉低30us后读取电平,整个时间片应该大于60us。
			在10us附近判断是否释放总线即可
  * @param  
  * @retval 
  */
void OneWire_SendBit(unsigned char Bit)

	OneWire_DQ = 0;									  //	拉低总线
	unsigned char i;
	
	i = 4;
	while (--i);											//	Delay 10us
	
	OneWire_DQ = Bit;
	
	i = 24;
	while (--i);											//	Delay 50us
	
	OneWire_DQ = 1;


接收一位

主机将总线拉低1 ~ 15us, 然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us末尾),读取低电平接收0,读取高电平接收1,整个时间片应该大于60us。

/**
  * @brief  主机将总线拉低1 ~ 15us, 然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us末尾),
						读取低电平接收0,读取高电平接收1,整个时间片应该大于60us。

  * @param  
  * @retval 
  */
unsigned char OneWrie_ReceiveBit()

	unsigned char Bit;
	unsigned char i;
	
	OneWire_DQ = 0;
	
	i = 2;
	while (--i);											//	Delay 5us
	
	OneWire_DQ = 1;
	
	i = 2;
	while (--i);											//	Delay 5us
	
	Bit = OneWire_DQ;
	
	i = 24;
	while (--i);											//	Delay 50us
	
	return Bit;

发送和接收一个字节

/**
  * @brief  发送一个字节
  * @param  Byte 发送的字节
  * @retval 
  */
void OneWire_SendByte(unsigned char Byte)

	unsigned char i;
	for(i = 0; i < 8; i++)
		OneWire_SendBit(Byte&(0x01<<i));
	

/**
  * @brief  接收一个字节
  * @param  
  * @retval 接收的数据
  */
unsigned char OneWire_ReceiveByte()

	unsigned char i;
	unsigned char Byte = 0x00;
	for(i = 0; i < 8; i++)
		if(OneWire_ReceiveBit())
			Byte |= (0x01<<i);
		
	
	return Byte;

DS18B20操作流程

  • 初始化:从机复位,主机判断从机是否响应
  • ROM操作:ROM指令 + 本指令需要的读写操作

ROM:

SEARCH ROM : 搜寻
READ ROM : 读
MATCH ROM : 匹配寻址
SKIP ROM :跳过,当接一个设备时使用
ALARM SEARCH :告警搜索

功能指令:

CONVERT T :温度变换
WRITE SCRATCHPAD:写
READ SCRATCHPAD:读暂存器内容
COPY SCRATCHPAD: 复制
RECALL E2:覆盖
READ POWER SUPPLY:响应供电方式,独立、寄生供电

  • 功能操作:功能指令 + 本指令需要的读写操作

DS18B20数据帧

  • 温度变化:初始化—>跳过ROM—>开始温度变换
  • 温度读取:初始化—>跳过ROM—>读暂存器—>连续的读操作

直流电机驱动

电机驱动电路

  • 大功率期间直接驱动
    不能调换正负方向
  • H桥驱动
    可以调控旋转方向

PWM电机调速

PWM 脉冲宽度调制,在具有惯性的系统中,可以通过对脉冲的宽度进行调制

代码实现

实现思路:通过定时器+中断+标志实现模拟出PWM

/**
  * @brief  中断处理
  * @desc   通过定时器控制频率,Counter和Compare的比较控制占空比
  * @param  无
  * @retval 无
  */
void Timer0_Routine() interrupt 1

	static unsigned int T0Count;
	TL0 = 0x9C;
	TH0 = 0xFF;
	Counter++;
	Counter%=100;
	if(Counter < Compare)
		LED = 1;
	 else 
		LED = 0;
	

IIC总线

IIC概述

IIC百科
SPI、UART、RS232、RS485、IIC 5种嵌入式经典通信总线协议精讲

IIC时序结构

Start

起始条件:SCL高电平期间,SDA从高电平切换到低电平

/**
  * @brief  起始
  * @param  
  * @retval 
  */
void I2C_Start(void)

	I2C_SDA = 1;
	I2C_SCL = 1;
	I2C_SDA = 0;
	I2C_SCL = 0;

Stop

终止条件:SCL高电平期间,SDA从低电平切换到高电平

/**
  * @brief  终止
  * @param  
  * @retval 
  */
void I2C_Stop(void)

	I2C_SDA = 0;
	I2C_SCL = 1;
	I2C_SDA = 1;

发送一个字节

SCL低电平期间,主机将数据位一次放到SDA先上(高位在前)
拉高SCL电平,从机在SCL高电平期间读取数据位
如此循环8次即可读一个字节

/**
  * @brief  发送一个字节
  * @param  
  * @retval 
  */
void I2C_SendByte(unsigned char Byte)

	unsigned char i;
	for(i = 0; i < 8; i++)
		I2C_SDA = Byte & (0x80 >> i);
		I2C_SCL = 1;
		I2C_SCL = 0;
	

接收一个字节

SCL低电平期间,从机将数据位依次放到SDA线上(高位在前)
拉高SCL,主机在SCL高电平时读取数据位
如此循环8次,即可接收一个字节(在接收前需要释放SDA,及SDA = 1)

/**
  * @brief  接收一个字节
  * @param  
  * @retval 
  */
unsigned char ReceiveByte(void)

	unsigned char i, Byte = 0x00;
	
	I2C_SDA = 1;
	
	for(i = 0; i < 8; i++)
		I2C_SCL = 1;
	
		if(I2C_SDA)
			Byte |= (0x80 >> i);
		
		
		I2C_SCL = 0;
	
	
	return Byte;

发送应答

在接收完一个字节后,主机在下一个时钟发送一位数据,0标识应答,1标识非应答

/**
  * @brief  I2C发送应答
  * @param  AckBit 应答位,0为应答,1为非应答
  * @retval 无
  */
void I2C_SendAck(unsigned char AckBit)

	I2C_SDA = AckBit;
	I2C_SCL = 1;
	I2C_SCL = 0;

接收应答

在发送完一个字节滞后,主机在下一个时钟接收一位数据,判断从机是否应答,0标识应答,1标识非应答(主机在接收前,需要释放SDA)

/**
  * @brief  I2C接收应答位
  * @param  无
  * @retval 接收到的应答位,0为应答,1为非应答
  */
unsigned char I2C_ReceiveAck(void)

	unsigned char AckBit;
	I2C_SDA = 1;
	I2C_SCL = 1;
	AckBit = I2C_SDA;
	I2C_SCL = 0;
	return AckBit;


IIC数据帧

发送一帧数据

接收一帧数据

紫色部分为从机发送

AT24C02应用

/**
  * @brief  AT24C02写入一个字节
  * @param  WordAddress 要写入字节的地址
  * @param  Data 要写入的数据
  * @retval 无
  */
void AT24C02_WriteByte(unsigned char WordAddress,Data)

	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_SendByte(Data);
	I2C_ReceiveAck();
	I2C_Stop();


/**
  * @brief  AT24C02读取一个字节
  * @param  WordAddress 要读出字节的地址
  * @retval 读出的数据
  */
unsigned char AT24C02_ReadByte(unsigned char WordAddress)

	unsigned char Data;
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS|0x01);
	I2C_ReceiveAck();
	Data = I2C_ReceiveByte();
	I2C_SendAck(1);
	I2C_Stop();
	return Data;


以上是关于51单片机学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

51单片机学习笔记_14 红外遥控

51单片机学习——点亮LED灯

51单片机学习——点亮LED灯

51单片机串口中断函数响应并返回后主函数运行到末尾后卡着不动,主函数无法循环了

MCS----51单片机外部中断请求信号有电平方式和______

51单片机自学笔记——独立按键