在28335上使用DS18B20測溫,並利用lcd12864顯示

好久沒用csdn寫文章了,目前主要的記錄都使用onenote,這次寫這個也主要是完成之前的一個未完成的事情。

ds18b20測溫,51就能完成,用dsp做純屬娛樂。當然,dsp與51之間的代碼有相似,也有差異。下面就開始詳細講解吧。

首先,ds18b20使用的是taobao購買的集成模塊,其結構以及電路如圖1所示:

圖1

之後大家要對ds18b20的工作時序進行詳細瞭解,不然。。。反正我吃過虧。具體時序在代碼中給出。

 

下面這段程序是整個程序的主函數,包含了   main以及IO口配置

/***************************************************
 * Lcd12864: RS:GPIO0;  RW:GND已經板載接地  ;EN:GPIO1 ;D0-D7:GPIO2-GPIO9
 * DS18B20 DQ:GPIO40/A0
 * 2019/06/15
 ***************************************************/

#include "DSP2833x_Project.h"
#include "lcd12864.h"
#include "ds18b20_para.h"
/********************
 * 定義全局變量
 ********************/

#define uchar  unsigned char

void init_port(void);
uchar Init_DS18B20();
uchar ReadOneChar(void);
void WriteOneChar(uchar dat);
float ReadTemperature();
void lcd_init(void);
void lcd_write_cmd(uchar cmd);			//可以理解爲寫進去是分配的地址類似scanf
void lcd_write_dat(uchar dat);			//同時
void LCD12864SetAddress_f( uchar x, uchar y ); 	 //地址轉換
void show(uchar x, uchar y, uchar * data);	

uchar table[7];


void main()
{
	float tt;
	int tt1;

	InitSysCtrl();
	init_port();
	DINT;
	InitPieCtrl();	//初始化中斷控制
	IER = 0x0000;
	IFR = 0x0000;
	InitPieVectTable();//初始化中斷矢量表

	lcd_init();
	while (1)
	{
		tt=ReadTemperature();
		tt1=tt*100+0.5;
		//留兩個小數點就*100,+0.5是四捨五入,因爲C語言浮點數轉換爲整型的時候把小數點
		//後面的數自動去掉,不管是否大於0.5,而+0.5之後大於0.5的就是進1了,小於0.5的就
		//算加上0.5,還是在小數點後面。

		table[0]=tt1/10000+0x30;  //百位
		table[1]=tt1%10000/1000+0x30;//十位
		table[2]=tt1%1000/100+0x30;//個位
		table[3]='.';
		table[4]=tt1%100/10+0x30;//個位;
		table[5]=tt1%10+0x30;//個位;
		table[6]='\0';
		show(0,0,table);
	}


}

void init_port(void)
{
	EALLOW;
		GpioCtrlRegs.GPBPUD.bit.GPIO40 = 0;    // 使能GPIO10 引腳內部上拉

		GpioCtrlRegs.GPBMUX1.bit.GPIO40 =0;   // 配置GPIO10爲通用I/O口

		GpioCtrlRegs.GPBQSEL1.bit.GPIO40 = 0;    // GPIO40與系統時鐘SYSCLKOUT 同步

		//lcd12864 use
		GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0;    // 使能GPIO0 引腳內部上拉

		GpioCtrlRegs.GPAPUD.bit.GPIO1 = 1;   // 禁止GPIO1 引腳內部上拉
		GpioCtrlRegs.GPAQSEL1.all = 0x0000;    // GPIO0-GPIO15與系統時鐘SYSCLKOUT 同步

		GpioCtrlRegs.GPADIR.all = 0x003FF;// 配置GPIO0-GPIO9爲輸出引腳

		//輸出數據LCD_RW和LCD_EN清零
		GpioDataRegs.GPADAT.bit.GPIO0 = 1;
		GpioDataRegs.GPADAT.bit.GPIO1 = 0;
    EDIS;
}

接下來,是主要部分,ds18b20的初始化和配置部分:

//這一部分是頭文件
/*
 * ds18b20_para.h
 *
 *  Created on: 2019年6月15日
 *      Author: wx
 */

#ifndef DS18B20_PARA_H_
#define DS18B20_PARA_H_

	#include "DSP2833x_Project.h"

	//---重定義關鍵詞---//
	#ifndef uchar
	#define uchar unsigned char
	#endif

	#define  DQ_DIR GpioCtrlRegs.GPBDIR.bit.GPIO40  //方向
	#define  DQ    GpioDataRegs.GPBDAT.bit.GPIO40//數值

	uchar Init_DS18B20();
	uchar ReadOneChar(void);
	void WriteOneChar(uchar dat);
	float ReadTemperature();

#endif /* DS18B20_PARA_H_ */
/*
 * ds18b20_para.c
 *
 *  Created on: 2019年6月15日
 *      Author: wx
 */

#include "ds18b20_para.h"

/*************************************************/
/*                  初始化函數                  */
/*************************************************/
uchar Init_DS18B20()
{
    EALLOW;
    DQ_DIR=1;     //設置爲輸出狀態
    EDIS;

    DQ=0;        //拉低電平
    DELAY_US(650);//延遲650us

    DQ=1;       //釋放總線
    DELAY_US(15);//延遲15us

    EALLOW;
    DQ_DIR=0;   //設置爲輸入狀態
    EDIS;

    while (DQ)
    {
    	DELAY_US(5000);//延遲5ms
    	return 0;      //初始化失敗
    }

   return 1;//成功

}

/*************************************************/
/*                讀字節子函數                  */
/*************************************************/
uchar ReadOneChar(void)
  {

    uchar i=0,dat=0;
    for (i=8;i>0;i--)
    {

        EALLOW;
        DQ_DIR=1;     //設置爲輸出狀態
        EDIS;

        DQ=0;
        DELAY_US(5);//延遲5us

        DQ=1;
		DELAY_US(6);//延遲6us,等待數據穩定


		dat>>=1;//讀到數據後右移一位

		EALLOW;
		DQ_DIR=0; //設置爲輸入狀態
		EDIS;

        if(DQ)
        	dat|=0x80;//取回最高位數據
        DELAY_US(60);//延遲60us
    }

   return dat;

}

 /*************************************************/
 /*                寫字節子函數                  */
 /*************************************************/
void WriteOneChar(uchar dat)
{
    uchar i;

	for(i=8;i>0;i--)
	{
		EALLOW;
		DQ_DIR=1; //設置爲輸出狀態
		EDIS;

		DQ=0;
		DELAY_US(5);//延遲5us

		DQ=dat & 0x01;
		DELAY_US(68);//延遲68us

		DQ=1;
		DELAY_US(5);//延遲5us
		dat >>=1;
	}
 }

//讀取溫度
float ReadTemperature()
{

	uchar a=0;
	uchar b=0;
	float t=0;
	uchar temp;

	Init_DS18B20();
	DELAY_US(1000);//延遲1ms
	WriteOneChar(0xCC); // 跳過讀序號列號的操作
	WriteOneChar(0x44); // 啓動溫度轉換

	Init_DS18B20();
	DELAY_US(1000);//延遲1ms
	WriteOneChar(0xCC); // 跳過讀序號列號的操作
	WriteOneChar(0xbe); //跳過讀序號列號的操作

	a=ReadOneChar();//低字節
	b=ReadOneChar();//高字節

	temp=b;
	temp<<=8;
	temp=temp|a;
	t=temp*0.0625;  //得到的是實際溫度

	return(t);

}

ok,上面這些就是溫度的採集以及轉換部分,主要的功能已經實現,下面就是使用12864進行顯示:

/*
 * lcd12864.h
 *
 *  Created on: 2019年6月15日
 *      Author: wx
 */

#ifndef LCD12864_H_
#define LCD12864_H_

	#include "DSP2833x_Project.h"

	//---重定義關鍵詞---//
	#ifndef uchar
	#define uchar unsigned char
	#endif

	#define LCD_RS GpioDataRegs.GPADAT.bit.GPIO0	//RS--GPIO0引腳,數據/指令選擇端
	//#define LCD_RW GpioDataRegs.GPADAT.bit.GPIO2    已經直接接地了
	#define LCD_EN GpioDataRegs.GPADAT.bit.GPIO1	//EN--GPIO1引腳
	#define LCD_DB GpioDataRegs.GPADAT.all

	void lcd_init(void);
	void lcd_write_cmd(uchar cmd);			//可以理解爲寫進去是分配的地址類似scanf
	void lcd_write_dat(uchar dat);			//同時
	void LCD12864SetAddress_f( uchar x, uchar y ); 	 //地址轉換
	void show(uchar x, uchar y, uchar * data);	

#endif /* LCD12864_H_ */
/*
 * lcd12864.c
 *
 *  Created on: 2019年6月15日
 *      Author: Administrator
 */
#include "lcd12864.h"

void lcd_init(void)
{
	DELAY_US(100000);//延遲100ms

	lcd_write_cmd(0x30);//設置8位格式,2行,5x8
	DELAY_US(200);//延遲200us

	lcd_write_cmd(0x0c);//整體顯示,關光標,不閃爍
	DELAY_US(200);//延遲200us

	lcd_write_cmd(0x01);//清除屏幕顯示:數據指針清零,所有顯示清零;
	DELAY_US(12000);//延遲200us

	lcd_write_cmd(0x06);//設定輸入方式,增量不移位
	DELAY_US(500);//延遲500us
}


void lcd_write_cmd(uchar cmd){
	LCD_EN=0;
	LCD_RS=0;         //指令
	//LCD_RW=0;         //寫入

		//起始位置爲0x80,對應GPIO0,若要在GPIO2上開始寫指令,需要將0x80左移兩位。
		LCD_DB=(cmd<<2)|0x0000;//賦值給D0-D7對應的GPIO2-GPIO9引腳,0x0000對應EN和RS,因爲前面都是0,所以這邊寫成0就可以了
		DELAY_US(500);			//讓數據穩定下來

	LCD_EN=1;          //執行寫指令(寫入時序)
	DELAY_US(1000);  //保持時間
	LCD_EN=0;
}


void lcd_write_dat(uchar dat){
	LCD_EN=0;
	LCD_RS=1;          //數據
	//LCD_RW=0;          //寫入

		LCD_DB=(dat<<2)|0x0001;//賦值給D0-D7對應的GPIO2-GPIO9引腳,0x0001對應 LCD_EN=0和LCD_RS=1;
		DELAY_US(500);

	LCD_EN=1;           //允許
	DELAY_US(1000);
	LCD_EN=0;
}

void LCD12864SetAddress_f( uchar x, uchar y )
{
	unsigned char byAddress;
	switch( y )
	{
		case 0 :
			byAddress = 0x80 + x;
			break;
		case 1 :
			byAddress = 0x90 + x;
			break;
		case 2 :
			byAddress = 0x88 + x;
			break;
		case 3 :
			byAddress = 0x98 + x;
			break;
		default :
			break;
	}
	lcd_write_cmd( byAddress ) ;
}


void show(uchar x,uchar y,uchar * data)
{
	LCD12864SetAddress_f( x, y );
	while (*data != '\0')
	{
	lcd_write_dat(*data);
	data++;			//地址 +1
	DELAY_US(500);  //延時500us
	}
}


以上就是代碼的所有部分。首先說明一下,這些代碼完全可用,但是針對不同demo板,引腳配置上會不同,需要各位看原理圖後再確定。

另外,我在調試的時候也發現一個bug,就是ds18b20在初始化的時候,無論是否成功,都會跳出(當然最後就是return 0了),但是不影響顯示,我也就沒去解決這個bug。如果各位有興趣,可以在自己的板子上試試。

接下來也不知道什麼時候有空再玩玩dsp了,之後打算把上面採集到的溫度數據通過串口發送給pc,並用txt或excel保存起來。ti的ccs裏有graph模塊,但是隻能讓你看,卻無法將時間序列上的數據導出,這是一個缺點。在使用飛思卡爾的freeMaster的時候,這個軟件具有數據導出爲txt的功能,還是很不錯的,希望ti能實現。

tips:ccs裏tool---save memory只能保存memory中的數據,時間序列上的點無法導出。我看到的是這樣的,如果大家有其他更好的方法,希望各位可以提出,大家一起學習。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章