⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb_thermometer.c

📁 USB温度采集系统的下位机程序
💻 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 + -