?? 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 + -