好久没用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数据的。只需在图像上右击即可。