This repository has been archived on 2024-12-31. You can view files and clone it, but cannot push or open issues or pull requests.
mfps/App/Src/m1820.c

233 lines
6.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "m1820.h"
#include "main.h"
#include "delay.h"
#define IO_H HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_SET) //PC10 Tx
#define IO_L HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_RESET) //PC10 Tx
#define IO_R HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_11) //PC11 Rx
void M1820_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; //PC11 Rx
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; //PC10 Tx
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
//单片机只需要用一个普通的IO口和M1820的DQ引脚相连然后控制这个IO口输出高低电平即可
//复位M1820
//作用:复位
void M1820_Rst(void)
{
// M1820_IO_OUT(); //把单片机的IO口配置为输出
IO_L; //拉低DQ
delay_us(750); //拉低750us这个时间是根据M1820本身的规则定的数据手册中480-960us
IO_H; //拉高DQ
delay_us(15); //15US
}
//等待M1820的回应
//作用检查单片机和M1820的通讯是否正常
//返回1:未检测到M1820的存在可能是DQ引脚没有上拉电阻通讯的时序不对芯片损坏等原因
//返回0:存在
uint8_t M1820_Check(void)
{
uint8_t retry=0;
// DS18B20_IO_IN();//SET PA0 INPUT
while ((IO_R == 1) && retry<200)
{
retry++;
delay_us(1);
};
if(retry>=200)return 1;
else retry=0;
while ((IO_R == 0) && retry<240)
{
retry++;
delay_us(1);
};
if(retry>=240)return 1;
return 0;
}
//从M1820读取一个位
//作用:读取一个位数据,重复调用该函数可以把温湿度数据读出来
//返回值1/0
uint8_t M1820_Read_Bit(void) // read one bit
{
uint8_t data;
// M1820_IO_OUT(); //单片机输出一个由低到高的上升沿脉冲给M1820
IO_L;
delay_us(2);
IO_H;
// M1820_IO_IN(); //把IO口配置为输入读取电平
delay_us(12);
if(IO_R)
{ //如果是高电平则M1820输出的数据是'1',否则为'0'
data = 1;
}
else
{
data = 0;
}
delay_us(50); //所有读时隙至少持续60us
return data;
}
//从M1820读取一个字节
//作用连续读8个位并合成一个字节数据
//返回值:读到的数据
uint8_t M1820_Read_Byte(void) // read one byte
{
uint8_t i,j,dat;
dat = 0;
for (i = 1;i <= 8;i++)
{
j = M1820_Read_Bit(); //连续调用8次
dat = (j << 7) | (dat >> 1);//先把之前的数据右移1位再把新读的数据置于最高位8次循环组成一个字节
}
return dat; //返回合成的1字节数据
}
//写一个字节到M1820
//作用写数据到M1820调用这个函数可以发送指令控制M1820
//dat要写入的字节
void M1820_Write_Byte(uint8_t dat)//数据传输必须先低后高
{
uint8_t j;
uint8_t testb;
// M1820_IO_OUT();//SET PA0 OUTPUT;
for (j = 1;j <= 8;j++)
{
testb = dat & 0x01; //把传进来的这个数据的最低位提取出来
dat = dat >> 1; //dat的数据右边移1位作用是把次高位移到最高位被移除的1位在上一行被testb记录
if (testb) //如果最低位数据为'1'
{
IO_L; // Write 1
delay_us(2); //两个写时隙时间恢复时间至少1us
IO_H; //输出60us高电平相当于告诉M1820要传的数据是'1'
delay_us(60); //所有写时隙至少持续60us
}
else //如果最低位数据为'0'
{
IO_L; //输出60us低电平相当于告诉M1820要传的数据是'0'
delay_us(60); //所有写时隙至少持续60us
IO_H;
delay_us(2); //两个写时隙时间恢复时间至少1us
}
}
}
//开始温度转换
//作用从M1820中读取温度数据
void M1820_Start(void) // ds1820 start convert
{
M1820_Rst(); //复位
M1820_Check(); //检查单片机和M1820的通讯是否正常
M1820_Write_Byte(0xcc); //寻址总线上的所有从设备详细说明可以参考数据手册ROM COMMANDS
M1820_Write_Byte(0x44); //0x44命令为启动温度转换命令详细说明可以参考数据手册ROM COMMANDS
}
//初始化M1820的IO口DQ 同时检测M1820的存在
//返回1:不存在
//返回0:存在
uint8_t M1820_Init(void)
{
// GPIO_InitTypeDef GPIO_InitStructure;
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PORTA口时钟
// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PORTA0 推挽输出
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// GPIO_Init(GPIOA, &GPIO_InitStructure);
// GPIO_SetBits(GPIOA,GPIO_Pin_0); //输出1
M1820_GPIO_Init(); //端口初始化
IO_H; //输出 1
M1820_Rst(); //复位
return M1820_Check();
}
//从M1820得到温度值
//精度0.1C
//返回值:温度值 -550~1250
char check = 1;
float M1820_Get_Temp(void)
{
uint8_t t_sign = 0;
uint8_t TL = 0,TH = 0;
short temp_1820 = 0;
M1820_Start (); //开始采集温度
M1820_Rst(); //复位
check = M1820_Check(); //检查单片机和M1820通讯是否正常
M1820_Write_Byte(0xcc); //寻址总线上的所有从设备详细说明可以参考数据手册ROM COMMANDS
M1820_Write_Byte(0xbe); //0x44命令为启动温度转换命令详细说明可以参考数据手册ROM COMMANDS
//数据由两个字节组成低位对应2^(-8)-2^(-1)高位对应2^(0)-2^(6)+最高位符号位分辨率为2^(-8)即1/256
TL = M1820_Read_Byte(); //读取数据低字节
TH = M1820_Read_Byte(); //读取数据高字节
if(TH > 7) //0x7F->01111111大于0x7F意味着最高位为1表示负数
{
t_sign = 0; //温度为负
}
else
{
t_sign = 1; //温度为正
}
temp_1820 = TH; //获得高字节数据
temp_1820 <<= 8; //高字节位左移8位
temp_1820 += TL; //左移的高8位加上低8位合成一个16位数据
// tem = (float)tem/256+40; //M1820Z手册 摄氏度 = ST/256 + 40低8位对应2^(-8)-2^(-1)高8位对应2^(0)-2^(6)+最高位符号位
float M1820_result = 0;
if(t_sign)
{
M1820_result = (float)temp_1820*0.0625;
return M1820_result; //返回温度值
}
else
{
temp_1820 = ~temp_1820; //取反
M1820_result = - (float)temp_1820*0.0625;
return M1820_result;
}
}
////执行
//float TEMP = 0;
//void M1820_Act(void)
//{
//// M1820_Init();
// TEMP = M1820_Get_Temp();
//}