📄 usb_thermometer.c
字号:
/*基于USB温度采集系统 USB_Thermometer( CH372A ) 单片机程序*/
//采用12.000MHZ 晶振//
//八路并行采集
//////////////////////////////////////////////////////
//////////////////////////////////////////////////////
#include <reg51.h>
#include <intrins.h>
#include "CH372INC.h"
//////////////////////////////////////////////////////
#define CH372_D0_D7 P2
#define StartTest 0x55
/*定义一些IO口的位*/
/////////////////////////////////////////////////////
sbit DQ=P1^0;
sbit CH372_A0=P1^1;
sbit CH372_RD=P1^2;
sbit CH372_WR=P1^3;
/*定义一些变量*/
////////////////////////////////////////////////////////
unsigned char Total=0;//DS18B20的个数
unsigned char Command;//命令代码
unsigned char Config; //配置寄存器变量
unsigned char SensorNum[8][8];//DS18B20序列号
unsigned char SendBuf[16];//一个数据块最多只能发送16字节
unsigned char RecvBuf[12];//一个数据块最多只能接收16字节
////////////////////////////////////////////////////////////////
//18b20的读取程序
/**************************************************************/
/*
void Delay(unsigned char i)// 3+2*i个机器周期
{
while(--i);
}
*/
/////////////////////////////////////////////////////////////////
void Delay50ms(unsigned char i) //延时50ms i 次
{
unsigned char j,k,l;
for(j=0;j<i;j++)
for(k=0;k<80;k++)
for(l=0;l<250;l++);
}
////////////////////////////////////////////////////////////////////
void Delay15() //延时15us
{ unsigned char i;
for(i=0;i<5;i++);
}
void Delay60() //延时60us
{
unsigned char i;
for(i=0;i<20;i++);
}
/*=========================================================
DS18B20驱动程序段
==========================================================*/
void WriteBit0() //写位0
{
DQ=1;
DQ=0;
Delay60();
DQ=1;
_nop_();
_nop_();
}
void WriteBit1() //写位1
{
DQ=1;
DQ=0;
_nop_();
_nop_();
DQ=1;
Delay60();
}
/*=======================================================*/
bit ReadBit() //读取数据位
{
bit b;
DQ=1;
DQ=0;
_nop_();
_nop_();
_nop_();
_nop_();
DQ=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
b=DQ;
Delay15();
Delay15();
Delay15();
_nop_();
_nop_();
return b;
}
/*=========================================================*/
void Reset_DS18B20() //复位
{
unsigned char i;
DQ=1;
DQ=0;
for(i=0;i<8;i++)
Delay60();
DQ=1;
while(DQ);
for(i=0;i<4;i++)
Delay60();
}
/*==============================================================*/
void WriteByte(unsigned char byte)//写一字节byte
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byte&0x01) //最低位是否为1?
WriteBit1();
else
WriteBit0();
byte=byte>>1; //字节右移1位
}
}
unsigned char ReadByte() //读一字节byte
{
unsigned char i,j;
bit b;
j=0;
for(i=0;i<8;i++)
{
b=ReadBit(); //读取一位
if(b) //为1否
j+=1;
j=_cror_(j,1); //循环右移1位
}
return j;
}
/*=============================================================*/
//---------------------------------------------------------------------------//
/*CH372_CS强制接地时*/
//////////////////////////////////////////////////////////////////////////
/*定义CH372写命令函数*/
//////////////////////////////////////////////////////////////////////////
void CH372_WR_CMD( unsigned char cmd)
{
CH372_D0_D7 = cmd;
CH372_A0=1;
CH372_WR=0;
CH372_WR=1;
CH372_A0=0;
CH372_D0_D7=0XFF;
}
///////////////////////////////////////////////////////////////////////////
/*定义CH372写数据函数*/
///////////////////////////////////////////////////////////////////////////
void CH372_WR_DATA( unsigned char dat)
{
CH372_D0_D7= dat;
CH372_WR=0;
CH372_WR=1;
CH372_D0_D7 = 0xFF;
}
///////////////////////////////////////////////////////////////////////////
/*定义CH372读数据函数*/
///////////////////////////////////////////////////////////////////////////
unsigned char CH372_RD_DATA()
{
/* 从CH372的数据端口读出数据,周期不小于1.5uS,如果单片机较快则延时 */
unsigned char dat;
CH372_D0_D7 = 0xFF; // 对于准双向I/O,请在此设置输出全高电平,便于输入
CH372_RD = 0;
dat =CH372_D0_D7;
CH372_RD = 1;
CH372_D0_D7 = 0xFF; //对于准双向I/O,请在此设置输出全高电平
return( dat );
}
/*CH372_CS强制接地时*/
//---------------------------------------------------------------------------//
//////////////////////////////////////////////////////////////////////////////
/*定义CH372初始化函数*/
//////////////////////////////////////////////////////////////////////////////
void CH372_Init()
{
unsigned char i;
CH372_WR_CMD( CMD_CHECK_EXIST ); /* 测试CH372是否正常工作 */
CH372_WR_DATA( 0x55 ); /* 写入测试数据 */
i = ~ 0x55; /* 返回数据应该是测试数据取反 */
if ( CH372_RD_DATA( ) != i )
{ /* CH372不正常 */
for ( i=80; i!=0; i-- )
{
CH372_WR_CMD( CMD_RESET_ALL ); /* 多次重复发命令,执行硬件复位 */
CH372_RD_DATA( );
}
CH372_WR_CMD( 0 );
Delay50ms(1); /* 延时50ms */
}
CH372_WR_CMD( CMD_SET_USB_MODE );/* 设置USB工作模式, 必要操作 */
CH372_WR_DATA( 2 ); /* 设置为使用内置固件的USB设备方式 */
for ( i=10; i!=0; i-- )
{ /* 等待操作成功,通常需要等待10uS-20uS */
if ( CH372_RD_DATA( ) == CMD_RET_SUCCESS ) break;
}
/* 下述启用中断,假定CH372连接在INT0 */
IT0 = 0; /* 置外部信号为低电平触发 */
IE0 = 0; /* 清中断标志 */
EA = 1;
EX0 = 1; /* 允许CH372中断 */
}
////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/* CH372中断服务程序,使用寄存器组1 */
//////////////////////////////////////////////////////////////////////////////
void CH372_Interrupt( ) interrupt 0
{
unsigned char InterruptStatus;
unsigned char i;
unsigned char j;
unsigned char RecvLength;//收数据长度
CH372_WR_CMD( CMD_GET_STATUS ); /* 获取中断状态并取消中断请求 */
InterruptStatus = CH372_RD_DATA( ); /* 获取中断状态 */
switch ( InterruptStatus )
{ /* 分析中断状态处理 */
case USB_INT_EP2_OUT:
{ /* 批量端点下传成功 */
CH372_WR_CMD( CMD_RD_USB_DATA ); /* 从当前USB中断的端点缓冲区读取数据块,并释放缓冲区 */
RecvLength = CH372_RD_DATA( ); /* 首先读取后续数据长度 */
for ( i=0;i<RecvLength;i++ )
RecvBuf[ i ] = CH372_RD_DATA( ); /* 接收数据包 */
Command=RecvBuf[0];//存储命令代码
if( Command==StartTest ) //判断是否是测试序列号
{
Reset_DS18B20();
WriteByte(0x33); //发读取DS18B20序列号的命令
for(i=0;i<8;i++)
SendBuf[i]=ReadByte();
Reset_DS18B20(); //总线复位
CH372_WR_CMD( CMD_WR_USB_DATA7 ); /* 向USB端点2的发送缓冲区写入数据块 */
CH372_WR_DATA( 0x08 ); /* 首先写入后续数据块长度 */
for ( i=0;i<8;i++ )
CH372_WR_DATA(SendBuf[ i ] ); /*发送数据块*/
}
else
{
Config=RecvBuf[ 11 ];//存储配置寄存器变量
for(i=0;i<8;i++)
{
SensorNum[Total][i]=RecvBuf[i+1];
}
Reset_DS18B20();
WriteByte(0x55); //发匹配目标DS18B20序列号的命令
for(i=0;i<8;i++)
WriteByte( RecvBuf[i+1]);//匹配目标DS18B20序列号
WriteByte(0x4E);//发写TH和TL报警温度命令
WriteByte(RecvBuf[9]);//发TH
WriteByte(RecvBuf[10]);//发TL
WriteByte(Config);//配置寄存器精度
Total++;
if(Total==Command)
{
Reset_DS18B20();
WriteByte(0xCC); //跳过匹配序列号
WriteByte(0x44); //发开始温度转换命令
switch(Config)//DS18B20温度转换等待函数
{
case 0x1F:
Delay50ms(2);
break;
case 0x3F:
Delay50ms(4);
break;
case 0x5F:
Delay50ms(8);
break;
case 0x7F:
Delay50ms(16);
break;
}
for(i=0;i<Command;i++)
{
Reset_DS18B20();
WriteByte(0x55); //发匹配目标DS18B20序列号的命令
for(j=0;j<8;j++)
WriteByte( SensorNum[i][j]);//匹配目标DS18B20序列号
WriteByte(0xBE);//读取温度
SendBuf[2*i]=ReadByte( );//读低字节
SendBuf[2*i+1]=ReadByte( );//读高字节
}
CH372_WR_CMD( CMD_WR_USB_DATA7 ); /* 向USB端点2的发送缓冲区写入数据块 */
CH372_WR_DATA( Command*2 ); /* 首先写入后续数据块长度 */
for ( i = 0; i < Command*2; i++ )
CH372_WR_DATA(SendBuf[ i ] ); /*发送数据块*/
Total=0;//清除Total
}
}
break;
}
case USB_INT_EP2_IN:
{ /* 批量数据发送成功 */
CH372_WR_CMD( CMD_UNLOCK_USB ); /* 释放当前USB缓冲区 */
if(Command!=StartTest)
{
Reset_DS18B20();
WriteByte(0xCC); //跳过匹配序列号
WriteByte(0x44); //发开始温度转换命令
switch(Config)//DS18B20温度转换等待函数
{
case 0x1F:
Delay50ms(2);
break;
case 0x3F:
Delay50ms(4);
break;
case 0x5F:
Delay50ms(8);
break;
case 0x7F:
Delay50ms(16);
break;
}
for(i=0;i<Command;i++)
{
Reset_DS18B20();
WriteByte(0x55); //发匹配目标DS18B20序列号的命令
for(j=0;j<8;j++)
WriteByte( SensorNum[i][j]);//匹配目标DS18B20序列号
WriteByte(0xBE);//读取温度
SendBuf[2*i]=ReadByte( );//读低字节
SendBuf[2*i+1]=ReadByte( );//读高字节
}
CH372_WR_CMD( CMD_WR_USB_DATA7 ); /* 向USB端点2的发送缓冲区写入数据块 */
CH372_WR_DATA( Command*2 ); /* 首先写入后续数据块长度 */
for ( i = 0; i < Command*2; i++ )
CH372_WR_DATA(SendBuf[ i ] ); /*发送数据块*/;
}
break;
}
default:
{ /* 其它中断,未用到,解锁后退出即可 */
CH372_WR_CMD( CMD_UNLOCK_USB ); /* 释放当前USB缓冲区 */
break;
}
}
}
////////////////////////////////////////////////////////////////////
/*主函数*/
////////////////////////////////////////////////////////////////////
void main()
{
EA=0;
Delay50ms(1);
CH372_Init();
while(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -