在28335上使用DS18B20测温,并利用lcd12864显示

本文介绍了如何在DSP上使用DS18B20温度传感器进行测温,并通过LCD12864显示结果。文章详细讲解了DS18B20的工作时序、程序主函数、初始化配置以及温度采集与显示过程。还提及了调试中遇到的bug和TI CCS的串口数据导出问题。
摘要由CSDN通过智能技术生成

好久没用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中的数据,时间序列上的点无法导出。我看到的是这样的,如果大家有其他更好的方法,希望各位可以提出,大家一起学习。

-------------------------------------------------------------------------------------------------------------------------------------------

2020-6-10更新

TI的CCS调试时的数据是可以导出为excel数据的。只需在图像上右击即可。

  • 13
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,以下是一个使用DS18B20测温,并将测温结果显示在LCD1602中的示例代码: ```python import os import glob import time import smbus # 定义DS18B20的设备文件路径 device_file = '/sys/bus/w1/devices/28-*/w1_slave' # 初始化LCD1602 def lcd_init(): # 打开I2C总线 bus = smbus.SMBus(1) # 设置LCD的地址 LCD_ADDR = 0x27 # 初始化LCD bus.write_byte_data(LCD_ADDR, 0x00, 0x38) bus.write_byte_data(LCD_ADDR, 0x00, 0x39) bus.write_byte_data(LCD_ADDR, 0x00, 0x14) bus.write_byte_data(LCD_ADDR, 0x00, 0x70) bus.write_byte_data(LCD_ADDR, 0x00, 0x56) bus.write_byte_data(LCD_ADDR, 0x00, 0x6c) time.sleep(0.2) bus.write_byte_data(LCD_ADDR, 0x00, 0x38) bus.write_byte_data(LCD_ADDR, 0x00, 0x0c) bus.write_byte_data(LCD_ADDR, 0x00, 0x01) time.sleep(0.2) return bus, LCD_ADDR # 在LCD上显示温度 def lcd_show_temperature(bus, LCD_ADDR, temperature): # 清空LCD屏幕 bus.write_byte_data(LCD_ADDR, 0x00, 0x01) time.sleep(0.2) # 将温度转化为字符串 temperature_str = '{:.2f}'.format(temperature) # 在LCD上显示温度 bus.write_byte_data(LCD_ADDR, 0x40, ord('T')) bus.write_byte_data(LCD_ADDR, 0x40+1, ord('e')) bus.write_byte_data(LCD_ADDR, 0x40+2, ord('m')) bus.write_byte_data(LCD_ADDR, 0x40+3, ord('p')) bus.write_byte_data(LCD_ADDR, 0x40+4, ord(':')) for i, c in enumerate(temperature_str): bus.write_byte_data(LCD_ADDR, 0x40+5+i, ord(c)) # 读取温度数据 def read_temperature(): # 找到DS18B20的设备文件路径 devicelist = glob.glob(device_file) if not devicelist: return None device_file = devicelist[0] # 读取设备文件中的温度数据 with open(device_file, 'r') as f: lines = f.readlines() # 解析温度数据 if lines[0].strip()[-3:] != 'YES': return None temperature = lines[1].find('t=') if temperature == -1: return None temperature = float(lines[1][temperature+2:]) / 1000.0 return temperature # 主函数 def main(): # 初始化LCD bus, LCD_ADDR = lcd_init() while True: # 读取温度 temperature = read_temperature() if temperature is not None: # 在LCD上显示温度 lcd_show_temperature(bus, LCD_ADDR, temperature) # 等待1秒钟 time.sleep(1) if __name__ == '__main__': main() ``` 这个程序首先会初始化LCD1602,并进入一个无限循环中。在每次循环中,程序会读取DS18B20的温度,并将温度值显示在LCD1602的第二行上。注意,这个程序需要使用SMBus库来控制I2C总线。另外,这个程序只在温度读取成功时才会更新LCD上的温度值。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值