登入帳戶  | 訂單查詢  | 購物車/收銀台( 0 ) | 在線留言板  | 付款方式  | 運費計算  | 聯絡我們  | 幫助中心 |  加入書簽
會員登入 新用戶登記
HOME新書上架暢銷書架好書推介特價區會員書架精選月讀2023年度TOP分類瀏覽雜誌 臺灣用戶
品種:超過100萬種各類書籍/音像和精品,正品正價,放心網購,悭钱省心 服務:香港台灣澳門海外 送貨:速遞郵局服務站

新書上架簡體書 繁體書
暢銷書架簡體書 繁體書
好書推介簡體書 繁體書

三月出版:大陸書 台灣書
二月出版:大陸書 台灣書
一月出版:大陸書 台灣書
12月出版:大陸書 台灣書
11月出版:大陸書 台灣書
十月出版:大陸書 台灣書
九月出版:大陸書 台灣書
八月出版:大陸書 台灣書
七月出版:大陸書 台灣書
六月出版:大陸書 台灣書
五月出版:大陸書 台灣書
四月出版:大陸書 台灣書
三月出版:大陸書 台灣書
二月出版:大陸書 台灣書
一月出版:大陸書 台灣書

『簡體書』基于MSP430单片机的控制系统设计

書城自編碼: 3004537
分類:簡體書→大陸圖書→計算機/網絡计算机理论
作者: 陈中、陈冲
國際書號(ISBN): 9787302462187
出版社: 清华大学出版社
出版日期: 2017-06-01
版次: 1 印次: 1
頁數/字數: 480/688000
書度/開本: 32开 釘裝: 平装

售價:HK$ 130.4

我要買

 

** 我創建的書架 **
未登入.


新書推薦:
环艺设计手绘:景观/室内 马克笔 手绘效果图技法精解
《 环艺设计手绘:景观/室内 马克笔 手绘效果图技法精解 》

售價:HK$ 95.8
明清与李朝时代
《 明清与李朝时代 》

售價:HK$ 81.6
感动,如此创造
《 感动,如此创造 》

售價:HK$ 71.8
商业人像摄影
《 商业人像摄影 》

售價:HK$ 95.8
抗争表演
《 抗争表演 》

售價:HK$ 74.4
咏春八斩刀
《 咏春八斩刀 》

售價:HK$ 83.8
聊不完的艺术家:跨界设计师穆夏
《 聊不完的艺术家:跨界设计师穆夏 》

售價:HK$ 117.6
失去的过去与未来的犯罪
《 失去的过去与未来的犯罪 》

售價:HK$ 59.8

 

編輯推薦:
本书内容新颖独特,涵盖了MSP430单片机控制系统的诸多内容。通过大量实例,介绍MSP430F169单片机的工作原理及设计方法,使读者对基于单片机的设计有了充分的认识。对于每个课题,首先进行硬件电路设计,再进行软件编程,注重对硬件电路设计和软件编程中可能遇到的问题进行详细解释,并提供问题的解决方法,*后通过实验证明设计的正确性。对于初学者可能遇到的困惑,作者深有体会,本书通过项目实例教学,起到解疑与启发的作用,并培养读者分析问题和解决问题的能力。
內容簡介:
本书主要介绍MSP430F169单片机设计方法,在适当阐述工作原理基础上,重点介绍了硬件电路图和软件编程,对于重要程序,解释编程方法并说明其工作原理。
全书共分9章:第1章为基础篇,着重MSP430单片机工作原理以及IAR编译软件的应用;第2~9章为单片机设计,包括硬件系统设计和软件编程。全书叙述简洁、概念清晰,提供了大量应用实例,具备完整的硬件电路图和软件清单,涵盖了MSP430F169单片机设计的诸多内容。
本书适合作为高等院校电气、自动化专业高年级本科生、研究生的及高校教师教学参考书,还可以供相关工程技术人员参考。
關於作者:
作者简介:陈中,盐城工学院教师,连续多年指导学生进行毕业设计以及学科竞赛,拥有丰富的教学、实践经验。发表过多篇关于单片机的论文,反响良好。已出版《基于STC89C52单片机的控制系统设计》《基于AVR单片机的控制系统设计》等五部著作,即将出版《基于STM32单片机的控制系统设计》一书。陈冲,盐城工学院教师,多年从事教学科研工作。曾获学校青年教师竞赛三等奖1项,完成市级科研项目3项,获市科技进步二等奖1项。发表过多篇具有较高学术水平的论文,先后编著《电力拖动控制系统与MATLAB仿真》《运动控制系统综合实验教程》等多部教材。
目錄
目录
第1章单片机原理概述及C编程语言

1.1MSP430单片机概述

1.2初步认识MSP430单片机

1.3MSP430F169单片机最小系统

1.4C语言概述

1.4.1C的变量与数据类型

1.4.2C的运算符和表达式

1.5常用的IO相关寄存器及操作

1.6C语言的程序结构

1.6.1顺序结构

1.6.2选择结构

1.6.3循环结构

1.7C语言的函数

1.8IO端口常用操作C语言描述及常用C语言解析

1.9把51单片机的C语言转换成MSP430单片机的C语言

1.10MSP430编译软件使用

1.11自制头文件方法

第2章单片机输出电路设计

2.1单片机控制系统设计概述

2.2液晶1602的显示

2.3液晶12864的显示

2.3.1液晶12864并行显示

2.3.2液晶12864串行显示

2.4LED点阵的显示

2.5液晶12232的显示

2.62.4in彩屏TFT的显示

2.6.12.4in彩屏TFT简介

2.6.2显存地址指针与窗口工作模式

2.6.3常用寄存器设置

第3章单片机输入电路设计

3.1键盘的输入电路

3.2带函数和小数点的计算器设计

3.3电子密码锁设计

3.4步进电机控制系统设计

3.5温度检测系统设计

3.6温湿度传感器的设计

3.7电子秤的设计

第4章定时器计数器和外部中断系统设计

4.1MSP430单片机时钟源

4.2定时器计数器概述

4.3TIMER_A工作模式

4.4定时器A模块捕获比较工作原理

4.5定时器计数器A与PWM

4.6外部中断的概述

4.7秒表设计

4.8红外遥控设计

4.9超声波测距系统设计

4.10定时器计数器B

4.11定时器计数器B与PWM

4.12直流电机控制系统设计

第5章串行通信

5.1串行通信概述

5.2USART相关寄存器

5.3串行通信协议

5.4串行通信系统设计

第6章I2C接口的应用

6.1I2C通信协议概述

6.2I2C模式操作

6.3I2C寄存器说明

6.4具有断电保护的电子密码锁设计

6.4.1AT24C02芯片简介

6.4.2具有断电保护的电子密码锁设计

第7章同步串行SPI接口

7.1同步串行SPI接口概述

7.2SPI相关寄存器

7.3SPI通信设计举例无线模块通信设计

第8章AD与DA转换器

8.1AD转换器概述

8.2ADC12结构及特点

8.3ADC相关寄存器设置

8.4ADC12转换模式

8.5AD应用实例

8.6DA转换器概述

8.7DAC12结构与性能

8.8DAC相关寄存器设置

8.9DAC12的操作及设置和应用

第9章单片机综合系统设计

9.1两路温度检测系统设计

9.2红外遥控直流电机调速系统设计

9.3无线通信直流电机调速系统设计

9.4用VB语言编制串行助手界面控制步进电机调速系统设计

9.5门禁控制系统设计

9.6蓝牙控制系统设计

9.7彩屏和摄像头控制系统设计

参考文献
內容試閱
前言
单片机又称为微机控制器Microcontroller,国外普遍称为MCUMicro Control Unit,其基本结构是将微型的基本功能部件: 中央处理器CPU、存储器、输入输出接口IO、定时器计数器、中断系统等全部集成在一个半导体芯片上。MSP430单片机和非增强型51单片机相比较,具有运行速度快、功能丰富等优点,属于16位单片机,寄存器的设置较多。实际上随着中高档单片机的发展,寄存器的设置越来越多。非增强型51单片机有的端口是准双向端口,而MSP430单片机的端口都是双向的,必须设置端口数据的输出或输入方向。51单片机的C语言程序可以部分移植到MSP430单片机,但两者有很多不同之处。现在国内单片机书籍多如牛毛,但大部分图书都是偏重于理论以及汇编语言,实际上单片机技术的实践性很强,要想学好单片机技术,比较好的方法就是多做实物,多练习。从作者的实践中看,单片机学习有两个问题。首先是仿真软件,Proteus软件的确有其长处,但其Bug也不少,尤其在数码管动态显示方面,缺点很大。作者遇到过很多种情况,仿真能够成功,但实物做不出来; 或实物做出来了,但仿真不行。其次是汇编语言,汇编语言有其优点,但非常烦琐,建议读者采用C语言编程。本书采用的是MSP430单片机的F169型号,书中所有的电路图都是完全按照引脚实物绘制。MSP430单片机有很多类型,但基本上都是大同小异,只要把一种类型搞通了,很容易掌握其他MSP430类型的单片机设计方法。本书主要是在作者和顾春雷、沈翠凤编著的《基于AVR单片机的控制系统设计》基础上改写的,增加了MSP430单片机相关的内容。书中论述部分主要参考了《MSP430单片机使用手册》,赵建,谢楷等编写的《MSP430系列16位超低功耗单片机教学实验系统实验教程》,书中部分资料来自互联网。在此向顾春雷、沈翠凤、赵建、谢楷等表示衷心感谢。本书是由盐城工学院陈中、陈冲共同编写,陈中统筹了全稿。全书共分为9章,第1章单片机原理概述和C语言编程,内容包括单片机的结构和组成,以及单片机最小系统,不同数据类型和IAR软件调试方法等; 第2章单片机输出电路设计,介绍液晶1602、液晶12864、点阵和液晶12232等显示的设计; 第3章单片机输入电路设计,包括键盘、计算器、密码锁、电子秤步进电机控制系统、温度检测系统等设计方法; 第4章定时器计数器以及中断系统设计,着重说明了不同方式PWM波的原理及设计方法; 第5章串行通信设计,着重介绍串行助手软件进行串行通信设计; 第6章TWI接口的应用,着重介绍断电保护电子密码锁的设计; 第7章同步串行SPI接口的设计,着重介绍无线模块通信设计; 第8章AD和DA转换系统设计; 第9章单片机综合系统设计,内容包括两路温度传感器温度检测、直流电机调速系统等。本书在编写过程中,由丁圣均完成了大部分设计,盐城工学院电气学院何洋、杨柳、张宝山、周鹏和黄雅琪等同学在硬件设计和软件编程方面也做出了大量工作。同时本书还得到安徽徽电科技股份有限公司朱代忠工程师的大力帮助和技术指导。盐城工学院电气学院各位领导以及同事也对本书的写作给予了大力支持和帮助,在此向他们表示衷心感谢。本书配套资源包括IAR编译软件、下载软件、字模软件、串行助手软件、端口驱动软件以及书中所有程序,请在清华大学出版社网站www.tup.com.cn下载。由于作者水平有限,书中肯定有许多不足之处,欢迎读者批评指正,作者可以为本书的内容提供技术支持。此外,本书还有与其配套的开发板。欢迎各位读者发邮件到zdzcz33@126.com与作者联系,谢谢。陈中陈冲
盐城工学院
2017年4月


第3章单片机输入电路设计
3.1键盘的输入电路
键盘是最常用的单片机输入电路,键盘主要分为两类,一类是独立式键盘,另一类是矩阵式键盘。如图31a所示为独立式键盘,虽然MSP430单片机工作电压为3.3V,其独立式键盘接的上拉电阻仍为4.8~10k。其工作原理是将对应端口设置为输入并上拉,当键盘未按下,相应的端口为高电平,当键盘被按下时,相应的端口被拉为低电平。在程序中通过查询方法判断端口是否为低电平,如果是,就进入此键盘处理程序。独立式键盘适合键盘数量较少的场合,因为占用单片机的端口较多,比如8个键盘都采用独立式键盘,就需要占用单片机8个端口,而矩阵式键盘可以节省单片机端口。矩阵式键盘见图31b。
图31独立式键盘和矩阵式键盘
对于矩阵式键盘通常采用扫描法,设矩阵式键盘接单片机P1口相应的端口。其工作原理是,先将P1.7~P1.4口设置为输出,其中有一位设置为低电平,其余设置为高电平。例如将P1.4设置为输出且低电平,将P1.7~P1.5设置为输出且为高电平,将P1.3~P1.0口设置为输入并上拉,用C语言描述,即P1DIR=0xf0;P1OUT=0xef。 然后读取P1口数值,即检测P1电压,如果没有按钮按下,则P1口电压数值保持不变,其数值仍为0xef,如果在矩阵式键盘第4列有按键按下,则P1电压数值发生变化,不再为0xef,假定标志为0的键盘按下,按键造成短路,则单片机P1.0端口就变成低电平,用C语言描述,即ifP1IN&0x01==0条件成立,把这个按键取键值为0keyvalue=0; 如果是标志为4的键盘按下,按键造成短路,则单片机P1.1端口就变成低电平; 即ifP1IN&0x02==0条件成立,把这个按键取键值为4keyvalue=4; 同理可以确定标志为8或12的键盘。然后再将P1.5设置为输出且低电平,P1.7、P1.6、P1.4设置为输出且高电平,将P1.3~P1.0口设置为输入并上拉,用同样的方法就能确定第3列键盘哪个键盘按下。同理就可以确定第2列、第1列哪个键盘被按下。对于矩阵式键盘,一般情况下,用9个键盘代表0~9的数值,称为数值键,而大于9的数值键盘可以代表其他功能,称为功能键。对于键盘操作还有一个重要问题,即键抖动现象,简单说来,虽然只按一下按键然后松开,但由于单片机运行程序速度很快,它能多次运行键盘程序,往往会认为按了多次键盘。对于消除键盘抖动,有硬件消抖和软件消抖,最常用的是软件消抖,有多种方法。其中一种方法是在程序中检测到按键按下后,延迟一段时间,在按键处理程序结束后,再延时一段时间,实践表明能够很好地解决键盘抖动问题。
3.2带函数和小数点的计算器设计设计要求有带函数和小数点的计算器设计,设计采用1602作为显示。此设计有一个小数点的位置问题,如果小数点位置是变化的,比如显示3.4或3.48,那么小数点就发生变化,称之为浮动小数点; 如果小数点的位置保持不变,比如显示3.40或3.48,称之为固定小数点。市面上的计算器都是采用浮动小数点,编程复杂得多,本次设计采用浮动小数点方法。第二个设计特点就是具有函数运算,把功能键复用,另加一个独立键,当按下独立键盘S1时,表明键盘当作了sina、cos、tang等功能用。其设计思路是,独立键S1未按下时,由于接上拉电阻,P3.0设置为输入,则P3.0输入为高电平,就运行四则运算程序; 独立键S1按下时,则P3.0输入为低电平,就运行函数程序了。按下复位键盘后,重新开始计算。当出现被除数为零时,液晶显示error input。函数的运算,最好的方法是加个头文件math.h,该头文件包含sina、cos、tang、ctang函数等运算。带函数和小数点的计算器硬件电路图如图32所示。
图32带函数和小数点的计算器设计电路图
采用8MHz晶振作为时钟源。P4口接矩阵式键盘,P3.0接独立式键盘。程序清单如下:
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define set_rs P1OUT|=BIT3
#define clr_rs P1OUT&=~BIT3
#define set_lcden P1OUT|=BIT5
#define clr_lcden P1OUT&=~BIT5
#define dataout P2DIR=0XFF
#define dataport P2OUT
#define anjian P3IN&BIT0
uchar keyvalue;
uchar wei0=0,fuhao=0,flag1=0,flag2=0;
uchar tab1[]={"sin"};
uchar tab2[]={"cos"};
uchar tab3[]={"tan"};
uchar tab4[]={"="};
uchar dis_flag=0,time_1s_ok;
uint num=0;
uint time=0;
uchar dis_flag;
uint i,j;
int t,a,shu,k;
int jd,jd1,result,result1;
uint time_counter;
void int_clk
{
unsigned char i;
BCSCTL1&=~XT2OFF; 打开XT振荡器
BCSCTL2|=SELM1 SELS;MCLK为8MHz,SMCLK为1MHz
do
{
IFG1&=~OFIFG; 清除振荡器错误标志
fori=0; i 0
{
write_date*s;
s;
}
}
void lcddelay
{
unsigned int j;
forj=400; j0; j--;
}
void lcd_posunsigned char x,unsigned char y
{
dataport=0x80 0x40*x y;
P1DIR|=BIT3 ;
P1DIR|=BIT5 ;
P2DIR=0xff;
clr_rs;
clr_lcden;
delay5ms ;
delay5ms ;
set_lcden;
delay5ms ;
clr_lcden;
}
void init
{
clr_lcden;
write_com0x38;
delay5ms ;
write_com0x0c;
delay5ms ;
write_com0x06;
delay5ms ;
write_com0x01;
}
void displayunsigned long int num
{
uchar dis_flag=0;
uchar table[7];
ifnum0
{
dis_flag=1;
table[0]=num%10 ''0'';
}
else ifnum9
{
dis_flag=2;
table[0]=num10 ''0'';
table[1]=num%10 ''0'';
}
else ifnum99
{
dis_flag=3;
table[0]=num100 ''0'';
table[1]=num10%10 ''0'';
table[2]=num%10 ''0'';
}
else ifnum999
{
dis_flag=4;
table[0]=num1000 ''0'';
table[1]=num100%10 ''0'';
table[2]=num10%10 ''0'';
table[3]=num%10 ''0'';
}
else ifnum9999
{
dis_flag=5;
table[0]=num10000 ''0'';
table[1]=num1000%10 ''0'';
table[2]=num100%10 ''0'';
table[3]=num10%10 ''0'';
table[4]=num%10 ''0'';
}
else ifnum99999
{
dis_flag=6;
table[0]=num100000 ''0'';
table[1]=num10000%10 ''0'';
table[2]=num1000%10 ''0'';
table[3]=num100%10 ''0'';
table[4]=num10%10 ''0'';
table[5]=num%10 ''0'';
}
else ifnum999999
{
dis_flag=7;
table[0]=num1000000 ''0'';
table[1]=num100000%10 ''0'';
table[2]=num10000%10 ''0'';
table[3]=num1000%10 ''0'';
table[4]=num100%10 ''0'';
table[5]=num10%10 ''0'';
table[6]=num%10 ''0'';
}
iffuhao==4&&flag1==1
{
ifdis_flag3
{
ifi==dis_flag-3
{
write_date''.'';
delay5ms;
}
}
}
write_datetable[i];
delay5ms;
}
}
uchar keyscanvoid
{
P4OUT=0xef;
ifP4IN&0x0f!=0x0f
{
delay5ms;
ifP4IN&0x0f!=0x0f
{
ifP4IN&0x01==0
keyvalue=1;
ifP4IN&0x02==0
keyvalue=2;
ifP4IN&0x04==0
keyvalue=3;
ifP4IN&0x08==0
keyvalue=4;
whileP4IN&0x0f!=0x0f;
}
}
P4OUT=0xdf;
ifP4IN&0x0f!=0x0f
{
delay5ms;
ifP4IN&0x0f!=0x0f
{
ifP4IN&0x01==0
keyvalue=5;
ifP4IN&0x02==0
keyvalue=6;
ifP4IN&0x04==0
keyvalue=7;
ifP4IN&0x08==0
keyvalue=8;
whileP4IN&0x0f!=0x0f;
}
}
P4OUT=0xbf;
ifP4IN&0x0f!=0x0f
{
delay5ms;
ifP4IN&0x0f!=0x0f
{
ifP4IN&0x01==0
keyvalue=9;
ifP4IN&0x02==0
keyvalue=0;
ifP4IN&0x04==0
keyvalue=10;
ifP4IN&0x08==0
keyvalue=11;
whileP4IN&0x0f!=0x0f;
}
}
P4OUT=0x7f;
ifP4IN&0x0f!=0x0f
{
delay5ms;
ifP4IN&0x0f!=0x0f
{
ifP4IN&0x01==0
keyvalue=12;
ifP4IN&0x02==0
keyvalue=13;
ifP4IN&0x04==0
keyvalue=14;
ifP4IN&0x08==0
keyvalue=15;
whileP4IN&0x0f!=0x0f;
}
}
return keyvalue;
}
void main
{
long int shu=0,shu1=0,shu1_1=0,shu2=0,shu2_1=0,shu3=0,shu4=0,shu5=0,i=0,a=0,result=0,jd=0;
uchar flag=1,mode=0;
uchar wei1=0,wei2=0;
float shu6=0,sj=0,pi=3.14159;
WDTCTL = WDTPW WDTHOLD; 关闭看门狗
int_clk;
dataout;
init;
P1DIR|=BIT3 BIT5;
P4DIR=0xf0;
while1
{
keyvalue=17;
keyscan;
shu=keyvalue;
lcd_pos0,0;
ifanjian==0
{
mode=1;
}
ifmode==1
{
lcd_pos0,0;
write_date''*'';
delay5ms;
ifshu10&&shuwei2
{
wei0=wei1;
fori=0; i
#include
#define uchar unsigned char
#define uint unsigned int
#define CPU_F double8000000
#define delayusx __delay_cycleslongCPU_F*doublex1000000.0 宏定义延时函数
#define delaymsx __delay_cycleslongCPU_F*doublex1000.0
uchar keyvalue;
uchar wei0=0,fuhao=0,flag1=0,flag2=0;
uchar tab[]={0,0,0,0};
uchar tab1[]={0,0,0,0};
uchar LED[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
#define LEP3OUT
#define LED0 P3OUT&=~BIT7
#define LED1 P3OUT|=BIT7
#define FMQP2OUT
#define FMQ0 P3OUT&=~BIT0
#define FMQ1 P3OUT|=BIT0
uchar dis_flag=0,time_1s_ok;
uint num=0;
uint time=0;
uchar dis_flag;
uint i,j;
int t,a,shu,k;
int jd,jd1,result,result1;
uint time_counter;
void int_clk
{
unsigned char i;
BCSCTL1&=~XT2OFF; 打开XT振荡器
BCSCTL2|=SELM1 SELS;MCLK为8MHz,SMCLK为1MHz
do
{
IFG1&=~OFIFG; 清除振荡器错误标志
fori=0; i9&&num99&&num999&&num
P4OUT=0xef;
ifP4IN&0x0f!=0x0f
{
delay5ms;
ifP4IN&0x0f!=0x0f
{
ifP4IN&0x01==0
keyvalue=1;
ifP4IN&0x02==0
keyvalue=2;
ifP4IN&0x04==0
keyvalue=3;
ifP4IN&0x08==0
keyvalue=4;
whileP4IN&0x0f!=0x0f;
}
}
P4OUT=0xdf;
ifP4IN&0x0f!=0x0f
{
delay5ms;
ifP4IN&0x0f!=0x0f
{
ifP4IN&0x01==0
keyvalue=5;
ifP4IN&0x02==0
keyvalue=6;
ifP4IN&0x04==0
keyvalue=7;
ifP4IN&0x08==0
keyvalue=8;
whileP4IN&0x0f!=0x0f;
}
}
P4OUT=0xbf;
ifP4IN&0x0f!=0x0f
{
delay5ms;
ifP4IN&0x0f!=0x0f
{
ifP4IN&0x01==0
keyvalue=9;
ifP4IN&0x02==0
keyvalue=0;
ifP4IN&0x04==0
keyvalue=10;
ifP4IN&0x08==0
keyvalue=11;
whileP4IN&0x0f!=0x0f;
}
}
P4OUT=0x7f;
ifP4IN&0x0f!=0x0f
{
delay5ms;
ifP4IN&0x0f!=0x0f
{
ifP4IN&0x01==0
keyvalue=12;
ifP4IN&0x02==0
keyvalue=13;
ifP4IN&0x04==0
keyvalue=14;
ifP4IN&0x08==0
keyvalue=15;
whileP4IN&0x0f!=0x0f;
}
}
return keyvalue;
}
void main
{
WDTCTL = WDTPW WDTHOLD; 关闭看门狗
int num=0;
int i,shu,shu2=0,aa=0,flag=0,flag1=0,shu1=0,shu3=0,shu4=0,shu5=0,shu6=0;
shu=0;
int_clk;
P1DIR=0xff;
P1OUT=0xff;
P2DIR=0xff;
P2OUT=0xff;
P3DIR=0xff;
P3OUT=0xff;
P4DIR=0xf0;
while1
{
keyvalue=17;
keyscan;
num=keyvalue;
ifnum
{
shu1=shu1*10 num;
shu=shu1;
}
ifnum=0&&num
{
shu2=shu2*10 num;
shu=shu2;
}
ifnum==11&&flag==0
{
shu=8888;
flag=1;
num=17;
}
else ifnum==11&&flag==1
{
num=17;
ifshu1==shu2
{
aa=0;
flag1=1;
LED1;
delayms2000;
LED0;
shu2=0;
}
else
{
flag1=0;
shu2=0;
aa=aa 1;
FMQ1;
delayms5;
FMQ0;
}
shu=8888;
}
ifaa==3
{
shu=0;
while1
{
P1OUT=0x00;
}
}
ifnum==12&&flag1==1
{
shu1=0;
shu2=0;
flag=0;
}
displayshu;
}
}
下面对一些程序进行解释:
ifnum==11&&flag==0
{
shu=8888;
flag=1;
num=17;
}
num数值为11是确认键,当确认键第一次按下后,之所以再写个num=17是为了防止蜂鸣器响,是因为num赋值为11后,即使没按任何键盘,从后面程序:
else
{
flag1=0;
shu2=0;
aa=aa 1;
FMQ1;
delayms5;
FMQ0;
}
shu=8888;
}
可以看出,shu1肯定不等于shu2,则蜂鸣器就响了。而写了num=17后,单片机就不再执行ifnum==11条件的程序,保证了操作正确。再看下面程序:
ifaa==3
{
shu=0;
while1
{
P1OUT=0x00;
}
}
这是第二次按下确认键时,对第二次的确认键计数,当第二次确认键达到3次后,就执行while1程序,进入了死循环,从而把电子密码锁锁死。电子密码锁锁死后,再按任何键都不起作用,数码管无显示。实际上这条语句可以再进行改进,在while1中可以再写两行程序,使得数码管显示E表明密码锁已经锁死。思路是将显示E的十六进制数赋值给P1口,位选使得第一个数码管亮即可,读者可以自己试一下。实物图如图35所示,
图a为实物通电前的状态; 图b为实物通电后的状态; 图c为设定密码,密码为: 1256; 图d为密码确定后显示; 图e为输入密码正确发光二极管灯亮。
图35实物展示图
3.4步进电机控制系统设计设计要求: 由按键把步进电机需要转动的圈数显示在12864上,按下某个键后,步进电机旋转,每减小1圈,都在液晶上实时显示出来。同时还有步进电机高低速切换、正反转控制功能。遇到紧急情况按下停止按钮时,电机停止,液晶圈数显示为零。步进电机28BYJ48是四相五线八拍电机,电压在DC5V~DC12V之间。当给步进电机施加一系列连续不间断的控制脉冲时,步进电机可以连续不断地旋转。每一个脉冲信号对应的是步进电机的某一相或两相绕组的通电状态的改变,也就使得对应的转子转过一定的角度即为一个步距角。当通电状态的改变完成一个完整的循环时,转子就能刚好转过一个完整的齿距。四相步进电机可以在不同的通电方式下运行,常见的通电方式有单单相绕组通电四拍ABCDA,双双相绕组通电四拍ABBCCDDAAB,八拍AABBBCCCDDDAA等。本设计使用的5V步进电机是4相5线式的减速步进电机,型号为28BYJ48。它是一种将电脉冲转化为角位移的执行机构。通俗一点讲: 当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度步进角。我们可以通过控制脉冲来控制角位移量,从而达到准确定位的目的; 同时我们也可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。由于单片机接口信号不够大,需要通过ULN2003放大再连接到相应的电机接口。ULN2003AN介绍: ULN2003AN是一个7路反向器电路,即当输入端为高电平时,ULN2003AN对应输出端为低电平; 当输入端为低电平时,ULN2003AN对应输出端为高电平。ULN2003AN的引脚排列如图36所示。
有些读者很奇怪,为什么步进电机要接ULN2003AN芯片,而不能直接接单片机端口,ULN2003AN芯片是如何工作的?下面来详细说明。由于单片机端口的输出或输入灌输电流较小,当负载需要较大电流时,就不能带动负载。以图37为例,假如单片机端口直接接步进电机,当PD5端口为低电平时,通过步进电机的电流路线如图37所示,由于输入到单片机端口的电流较小,就不能带动步进电机。
图36ULN2003AN引脚图
图37单片机控制步进电机示意图
那么单片机接口接ULN2003AN芯片,再看如何工作的。以图38为例来进行说明。
图38单片机通过ULN2003AN芯片控制步进电机示意图
当单片机端口P1为输出状态且P1.6为高电平时,ULN2003AN芯片的反向作用,对应的端口OUT4为低电平,则电流如图虚线所示。由于ULN2003AN芯片可以输入较大的电流,从而带动步进电机运行。实际上单片机正是因为端口的输入或输出电流较小,带功率较大负载时往往需要加驱动电路,很多驱动的工作原理与以上相同。整个硬件电路图如图39所示。
图39基于单片机的控制步进电机电路图
矩阵式键盘接P5口,液晶采用串行控制方式。整个程序清单如下:
#include
typedef unsigned char uchar;
typedef unsigned int uint;
uchar keyvalue,key_shu,shu5,v,k,dis_flag;
int a;
uchar table[7]="";
uchar tab0[]={"步进电机调速系统"};
uchar tab1[]={"设定圈数:"};
uchar tab2[]={"高速"};
uchar tab3[]={"低速"};
uchar tab4[]={"正转"};
uchar tab5[]={"反转"};
#define SID BIT1
#define SCLK BIT2
#define CSBIT0
#define LCDPORT P4OUT
#define SID_1LCDPORT |= SID SID置高P4.1
#define SID_0 LCDPORT &= ~SIDSID置低
#define SCLK_1 LCDPORT |= SCLKSCLK置高P4.2
#define SCLK_0 LCDPORT &= ~SCLK SCLK置低
#define CS_1LCDPORT |= CS CS置高P4.3
#define CS_0LCDPORT &= ~CSCS置低
void int_clk
{
unsigned char i;
BCSCTL1&=~XT2OFF; 打开XT振荡器
BCSCTL2|=SELM1 SELS; MCLK为8MHz,SMCLK为1MHz
do
{
IFG1&=~OFIFG; 清除振荡器错误标志
fori=0;i0;i--
forj=120;j0;j--;
}
void delay_msuint aa
{
uint ii;
forii=0;ii
P5OUT=0xef;
ifP5IN&0x0f!=0x0f
{
delay_ms10;
ifP5IN&0x0f!=0x0f
{
ifP5IN&0x01==0
keyvalue=1;
ifP5IN&0x02==0
keyvalue=2;
ifP5IN&0x04==0
keyvalue=3;
ifP5IN&0x08==0
keyvalue=4;
whileP5IN&0x0f!=0x0f;
}
}
P5OUT=0xdf;
ifP5IN&0x0f!=0x0f
{
delay_ms10;
ifP5IN&0x0f!=0x0f
{
ifP5IN&0x01==0
keyvalue=5;
ifP5IN&0x02==0
keyvalue=6;
ifP5IN&0x04==0
keyvalue=7;
ifP5IN&0x08==0
keyvalue=8;
whileP5IN&0x0f!=0x0f;
}
}
P5OUT=0xbf;
ifP5IN&0x0f!=0x0f
{
delay_ms10;
ifP5IN&0x0f!=0x0f
{
ifP5IN&0x01==0
keyvalue=9;
ifP5IN&0x02==0
keyvalue=0;
ifP5IN&0x04==0
keyvalue=10;
ifP5IN&0x08==0
keyvalue=11;
whileP5IN&0x0f!=0x0f;
}
}
P5OUT=0x7f;
ifP5IN&0x0f!=0x0f
{
delay_ms10;
ifP5IN&0x0f!=0x0f
{
ifP5IN&0x01==0
keyvalue=12;
ifP5IN&0x02==0
keyvalue=13;
ifP5IN&0x04==0
keyvalue=14;
ifP5IN&0x08==0
keyvalue=15;
whileP5IN&0x0f!=0x0f;
}
}
return keyvalue;
}
void sendbyteuchar zdata 数据传送函数
{
uint i;
fori=0;i0
{
write_dat*S;
S;
}
}
void displayint num
{
ifnum=0
{
dis_flag=1;
table[0]=num%10 ''0'';
table[1]='' '';
fork=0;k9
{
dis_flag=2;
table[0]=num10 ''0'';
table[1]=num%10 ''0'';
table[2]='' '';
fork=0;k99
{
dis_flag=3;
table[0]=num100 ''0'';
table[1]=num10%10 ''0'';
table[2]=num%10 ''0'';
table[3]='' '';
fork=0;k999
{
dis_flag=4;
table[0]=num1000 ''0'';
table[1]=num100%10 ''0'';
table[2]=num10%10 ''0'';
table[3]=num%10 ''0'';
table[4]='' '';
fork=0;k0
{
mode=1;
}
else
{
mode=0;
flag=0;
}
ifkey_shu==10
{
flag=1;
shu1=0;
}
ifkey_shu==11 {v=1; lcd_pos2,6;hzkdistab2;}
ifkey_shu==12 {v=4; lcd_pos2,6; hzkdistab3;}
ifkey_shu==13 {d=0; lcd_pos2,0; hzkdistab4;}
ifkey_shu==14{d=1; lcd_pos2,0;hzkdistab5;}
ifkey_shu==15
{
shu=0;
P1OUT|=0x60;
}
ifmode==1&&flag==1
{
ifd==0
{
P1OUT=0x1c;
delay_msv;
P1OUT=0x0c;
delay_msv;
P1OUT=0x2c;
delay_msv;
P1OUT=0x24;
delay_msv;
P1OUT=0x34;
delay_msv;
P1OUT=0x30;
delay_msv;
P1OUT=0x38;
delay_msv;
P1OUT=0x18;
delay_msv;
a;
}
else
{
P1OUT=0x18;
delay_msv;
P1OUT=0x38;
delay_msv;
P1OUT=0x30;
delay_msv;
P1OUT=0x34;
delay_msv;
P1OUT=0x24;
delay_msv;
P1OUT=0x2c;
delay_msv;
P1OUT=0x0c;
delay_msv;
P1OUT=0x1c;
delay_msv;
a;
}
}
ifa==512
{
P1OUT=0x00;
a=0;
shu--;
}
lcd_pos1,5;
displayshu;
}
}部分程序说明:首先看步进电机通电方式。首先将P1口设置为输出(P1DIR = 0xff)。语句P1OUT=0x1c表明除P1.5输出低电平外,P1.4~P1.2输出均是高电平,对应ULN2003AN的OUT4就输出高电平,步进电机A相绕组通电。delay1v作用是调速,根据v的不同,步进电机的转速就发生变化。语句P1OUT=0x0c表明除P1.5、P1.4输出低电平外,P1.3~P1.2输出均是高电平。对应ULN2003AN的OUT4、OUT3就输出高电平,步进电机A相、B相绕组通电。延时后P1OUT=0x2c表明除P1.4输出低电平外,P1.5、P1.3、P1.2输出均是高电平。对应ULN2003AN的OUT3就输出高电平,步进电机B相绕组通电。依此类推,可以看出步进电机采用八拍(AABBBCCCDDDAA)供电方式。ifkey_shu==11和ifkey_shu==12的区别是延时函数的参数(v)不同,造成了步进电动机转速改变,并在液晶上显示。由于步进电机28BYJ48内部机械结构,通电循环了512次电机才旋转一圈,所以ifa==512,把液晶显示圈数减1。
图310实物展示图
ifkey_shu==13 和 ifkey_shu==14{}的作用是正反转切换并在液晶上显示。ifkey_shu==15)的作用是急停,当按下对应的按钮后,步进电机停止,同时液晶显示的圈数为0。本次设计实物展示如图310所示。设定好圈数后,按正(反)转和高(低)速按钮后,再按确认键,步进电机按照设定的控制方式运行。
3.5温度检测系统设计DS18B20数字温度计提供9~12位二进制温度读数,以指示器件温度。数据经过单线接口送入DS18B20或从DS18B20送出,因此从主机CPU到DS18B20仅需一条线。每一个DS18B20在出厂时,就设定了唯一的64位长的序号,因此可以将多个DS18B20连接在单线总线上,这就可以在许多不同的地方放置DS18B20,并使用一条总线连接在一起。DS18B20的测量范围为-55℃~ 125℃,最小分辨率为0.0625℃。DS18B20采用与常用的小功率三极管相同的TO92封装方式。DS18B20内部地址分配如表31所示的9字节RAM。其中字节0和字节1存放DS18B20的温度测量值,字节4存放配置字节,用于设定温度测量的分辨率等参数,字节8是DS18B20自己生成的循环余校验码,在CPU读取DS18B20数据时,用于检查读取数据的正确性。
表31DS18B20内部RAM分配
字节0温度值低字节TL字节5保留字节1温度值高字节TH字节6保留字节2TL或用户字节1字节7保留字节3TH或用户字节2字节8CRC校验字节字节4配置字节
主CPU经DQ向DS18B20发送温度测量等变换命令,DS18B20将测量的温度值存放在DS18B20的RAM的字节0和字节1中,除温度变换命令外,再介绍几个命令,见表32。
表32DS18B20的部分命令
指令代码十六进制指令代码十六进制
Skip ROM跳过ROMCChRead Scratchpad读RAMBEhConvert Temperature温度变换44hWrite Scratchpad写RAM4Eh
命令CCh,跳过ROM。该命令跳过ROM中的64位长的序号,即不关心每一个DS18B20中唯一序号,因此该命令只能在一总线上仅接有一个DS18B20时应用。在仅使用单个DS18B20时,使用该命令可以简化程序。命令44h,温度变换。DS18B20接收到该命令后将触发温度测量,收到命令数百毫秒后,温度才能测量完毕,将测量的值存入RAM的字节0和字节1中。命令BEh,读RAM存储器。该命令读取DS18B20内部RAM中的数据。读取数据中的头两个字节就是测量的温度值。DS18B20收到BEh命令后,将内部RAM中的数据释放到一总线DQ上。设定DS18B20使用默认的12位转换,DS18B20内部RAM中温度值存放在字节0TL和字节1TH中,TL和TH的格式如下:
TLbit7bit6
bit5
bit4
bit3
bit2
bit1
bit0
232221202-12-22-32-4
THbit15bit14bit13bit12bit11bit10bit9bit8SSSSS262524
存储器TH中的bit15~bit11为符号位,如果温度为负数,则bit15~bit11全为1,否则全为0。存储器TH的bit10~bit8及存储器TL共11位存储温度值。TL的bit3~bit0存储温度的小数部分TLLSB的1的表示0.0625℃,如果温度是负数,将存储器中的二进制求反加1,再分别将整数部分和小数部分转换成十进制数合并后就得到被测温度值。比如,当DS18B20的数据为0000 0000 1010 0010,即TH=0000 0000、TL=1010 0010,根据TL和TH的格式计算温度值为260 250 240 231 220 211 200 2-10 2-20 2-31 2-40=10.125℃当DS18B20的数据为1111 1111 0101 1110,即TH=1111 1111、TL=0101 1110,表明所测温度为负值,取反得加1得0000 0000 1010 0010,根据TL和TH的格式计算温度值为260 250 240 231 220 211 200 2-10 2-20 2-31 2-40=-10.125℃DS18B20中测试数据与温度值对应关系如表33所示。
表33DS18B20中测量数据与温度值对应关系的例子
温度二进制输出十六进制输出
125℃0000 0111 1101 000007D0h 85℃0000 0101 0101 00000550h 25.0626℃000 0001 1001 00010191h 10.125℃0000 0000 1010 001000A2h
0.5℃0000 0000 0000 10000008h0℃0000 0000 0000 00000000h-0.5℃1111 1111 1111 1000FFF8h-10.125℃1111 1111 0101 111FF5Eh-25.0625℃1111 111 0110 1111FE6Fh-55℃1111 1100 1001 0000FC90h
由于单片机与DS18B20通过一总线进行数据交换,无论读和写均是从最低位开始,数据线DQ是双向的,既承担单片机DS18B20传输命令,也是DS18B20向单片机回送温度等数据的通道,因此时序关系十分重要,有3个关键时序需要掌握。
1. DS18B20的初始化DS18B20的初始化是由单片机控制的,是DS18B20一切命令的初始条件,DS18B20的初始化时序如图311所示,主机发送一个复位脉冲接着释放总线并进入接收状态,DS18B20会在检测到上升沿后等待,然后发送一个低电平的存在脉冲告知主机,主机在60~240s的期间接收到低电平,即表示DS18B20存在,并已初始化成功。
图311DS18B20初始化时序图
图311看起来比较晦涩,下面把这图标注一下,如图312所示。
图312DS18B20初始化时序图标注
用程序描述如下。假设DS18B20的DQ引脚接单片机P6.5端口。
void DS18B20_RESETvoid复位
{
SDAOUT;
DS18B20_DQ_L;
delay_us550; 至少480s的低电平信号
DS18B20_DQ_H; 拉高等待接收18B20的存在脉冲信号
delay_us60;
SDAIN;
delay_us1;
DS18B20_Presence=SDADATA; 检测DQ电压,如果DQ是低电平,就表明DS18B20存在或正常,如果DQ是高电平,就表明没有DS18B20或损坏
delay_us200;
}
2. DS18B20的写时序如图313所示,整个写时间隙需要持续至少,连续写2位数据的间隙最小,主机将总线由高电平拉至低电平后就触发了一个写时间间隙,主机必须在15s内将所写的位送到总线上。DS18B20在15~60s间开始对总线进行采样,如果此时总线为低电平,写入的位是0; 若为高电平,写入的位是1。
同样也把这图标注一下,如图314所示。
用程序描述如下:
void Write_DS18B20_OneCharuchar dat 写一个字节
{
uchar i=0;
fori=8; i0; i--
{
SDAOUT;
DS18B20_DQ_L;
delay_us6;
ifdat&0x010 DS18B20_DQ_H;
Else DS18B20_DQ_L;
delay_us50;
DS18B20_DQ_H;
dat=1;
delay_us10;
}
}
图313DS18B20的写时序
图314DS18B20的写时序标注
现在假如我们希望向DS18B20写数dat为1101 0001D7~D0,注意在写的过程中是低位在前,高位在后,i=0,一开始DS18B20_DQ_L拉低总线,因为dat第一位D0是高电平1,满足ifdat&0x010条件。DS18B20采样是高电平1,就知道写的是1。延时后,又把总线拉高DS18B20_DQ_H,表明1写入。dat = 1的作用是右移,把dat的数据变为0110 1000。i=1,DS18B20_DQ_L,不满足ifdat&0x010条件。DS18B20采样是低电平0,就知道写的是0。延时后,又把总线拉高DS18B20_DQ_H,表明0写入。这样重复8次,就把1101 0001写入DS18B20。3. DS18B20的读时序如图315所示主机将总线由高电平拉至低电平并保持1后释放总线就产生了一个读时间隙。读时间隙产生后DS18B20会将1或0传至总线,若传送0则拉低总线,若传送1则保持总线为高电平。在读时间隙产生后的15s内为主机采集数据时间。
图315DS18B20的读时序
把图315标注一下,如图316所示。
图316DS18B20的读时序标注
图316就比较容易理解DS12B读的时序图,一开始由主机把DQ拉高,然后把DQ拉低,再释放总线DQ=1,再检测DQ的电压,如果DQ电压为0,就表明写的是0,如果DQ电压为高电平,就表明读的是1,再把总线拉高,表明一位数据读完。用程序描述如下:
uchar Read_DS18B20_OneCharvoid读一个字节
{
uchar date=0;
uchar j=0;
forj=8; j0; j--
{
DS18B20_DQ_L;
date=1;
delay_us2;
DS18B20_DQ_H;
delay_us5;
SDAIN;
delay_us1;
ifSDADATA0
date|=0x80;
delay_us30;
SDAOUT;
DS18B20_DQ_H;
delay_us5;
}
return date;
}
现在假如我们读DS18B20的数为1101 0101D7~D0,注意读还是低字节在前,高字节在后,j=0时,一开始DS18B20_DQ_L拉低总线,初始date为0000 0000,然后date右移一位,仍为0000 0000,DS18B20_DQ_H就是释放总线,被读的数第一位是1因为DQ输出了高电平。ifSDADATA0的含义是如果DQ不为0,主机采样就成立,date |= 0X80后,date数据就是1000 0000,延时delay_us30,再把总线输出并拉高SDAOUT,DS18B20_DQ_H,第一位采样就完成。j=1, DS18B20_DQ_L拉低总线,右移位后,date数据就变为0100 0000,释放总线DS18B20_DQ_H,因为被读的数第二位是0表明DQ输出是低电平,主机采样是低电平,不满足ifSDADATA0的条件,date数据保持不变,仍为0100 0000。再把总线输出并拉高SDAOUT,DS18B20_DQ_H,第二位采样就完成。j=2,DS18B20_DQ_L; 拉低总线,右移位后,date数据就变为0010 0000,释放总线DS18B20_DQ_H,因为被读的数第三位是1因为DQ输出了高电平,主机采样是高电平,满足ifSDADATA0的条件,date |= 0X80后,date就变为1010 0000。再把总线输出并拉高SDAOUT,DS18B20_DQ_H,第三位采样就完成这样重复8次后,读DS18B20的数就为1101 0101。由于单片机仅接一个DS18B20,所以可以省掉读取序列号及匹配等过程,即直接使用命令[CCh]跳过ROM。硬件电路图如图317所示。
图317基于单片机的温度检测控制系统设计电路图
从电路图可以看出,DS18B20的DQ端接单片机P6.5口,液晶数据端口接P2口,RS接单片机P1.3口,RW接地,E接单片机P1.5口。DS18B20的DQ端与电源端之间的电阻4.7k即为上拉电阻。特别需要注意的是DS18B20电源接3.3V,而不能接5V。这是因为DS18B20工作电压在2.0~5.5V之间,而MSP430单片机端口电压是3.3V,如果DS18B20接5V工作电源,就不能读出数据。整个程序清单如下:
#include
#define CPU_F double8000000
#define delay_usx __delay_cycleslongCPU_F*doublex1000000.0
#define delay_msx __delay_cycleslongCPU_F*doublex1000.0
#define uchar unsigned char
#define uchar unsigned char
#define uint unsigned int
#define set_rs P1OUT|=BIT3
#define clr_rs P1OUT&=~BIT3
#define set_lcden P1OUT|=BIT5
#define clr_lcden P1OUT&=~BIT5
#define dataout P2DIR=0XFF
#define dataport P2OUT
#define DS18B20_DQ_LP6OUT&=~BIT5
#define DS18B20_DQ_HP6OUT|=BIT5
#define SDAOUT P6DIR|=BIT5
#define SDAIN P6DIR&=~BIT5
#define SDADATA P6IN&BIT5
uchar Tem_dispbuf[5]={0,0,0,0,0};显示数据暂存
uchar Tem_dispbuf1[5]={0,0,0,0,0};显示数据暂存
uchar DS18B20_Temp_data[4]={0x00,0x00,0x00,0x00}; 储存温度值的数组
uchar DS18B20_Temp_data1[4]={0x00,0x00,0x00,0x00}; 储存温度值的数组
uchar DS18B20_TEM_Deccode[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,温度小数位查表数组
0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
uchar DS18B20_Presence,state; 18b20复位成功标示位,=0 成功,=1 失败
uchar tab[]={"TEMP: "};
void int_clk
{
unsigned char i;
BCSCTL1&=~XT2OFF; 打开XT振荡器
BCSCTL2|=SELM1 SELS;MCLK为8MHz,SMCLK为1MHz
do
{
IFG1&=~OFIFG; 清除振荡器错误标志
fori=0; i 复位
{
SDAOUT;
DS18B20_DQ_L;
delay_us550; 至少480s的低电平信号
DS18B20_DQ_H; 拉高等待接收18B20的存在脉冲信号
delay_us60;
SDAIN;
delay_us1;
DS18B20_Presence=SDADATA;
delay_us200;
}
void Write_DS18B20_OneCharuchar dat 写一个字节
{
uchar i=0;
fori=8; i0; i--
{
SDAOUT;
DS18B20_DQ_L;
delay_us6;
ifdat&0x010
DS18B20_DQ_H;
else
DS18B20_DQ_L;
delay_us50;
DS18B20_DQ_H;
dat=1;
delay_us10;
}
}
uchar Read_DS18B20_OneCharvoid读一个字节
{
uchar date=0;
uchar j=0;
forj=8; j0; j--
{
DS18B20_DQ_L;
date=1;
delay_us2;
DS18B20_DQ_H;
delay_us5;
SDAIN;
delay_us1;
ifSDADATA0
date|=0x80;
delay_us30;
SDAOUT;
DS18B20_DQ_H;
delay_us5;
}
return date;
}
***********读DS18B20温度**************
void Read_18B20_Temperature1
{
DS18B20_RESET; 复位18B20
ifDS18B20_Presence==0复位成功
{
Write_DS18B20_OneChar0XCC; 跳过读序列号
Write_DS18B20_OneChar0X44; 启动温度转换
delay_us5; 等待温度转换时间500s左右
delay_us620;
DS18B20_RESET; 复位18B20
Write_DS18B20_OneChar0xCC; 发送匹配ROM指令
Write_DS18B20_OneChar0xBE;
delay_us620;
DS18B20_Temp_data[0]=Read_DS18B20_OneChar;Temperature LSB
DS18B20_Temp_data[1]=Read_DS18B20_OneChar;Temperature MSB
Tem_dispbuf[0]=DS18B20_TEM_Deccode[DS18B20_Temp_data[0]&0x0f]; 小数位
Tem_dispbuf[4]=DS18B20_Temp_data[1]&0x0f4;取出温度值的整数位
Tem_dispbuf[3]=Tem_dispbuf[4]100;
Tem_dispbuf[2]=Tem_dispbuf[4]%10010;
Tem_dispbuf[1]=Tem_dispbuf[4]%10;
delay_us800;
}
delay_us5;
}
void write_comuchar com1602写命令
{
P1DIR|=BIT3 ;
P1DIR|=BIT5 ;
P2DIR=0xff;
clr_rs;
clr_lcden;
P2OUT=com;
delay5ms;
delay5ms;
set_lcden;
delay5ms;
clr_lcden;
}
void write_dateuchar date1602写数据
{
P1DIR|=BIT3 ;
P1DIR|=BIT5 ;
P2DIR=0xff;
set_rs;
clr_lcden;
P2OUT=date;
delay5ms;
delay5ms;
set_lcden;
delay5ms;
clr_lcden;
}
void lcddelay
{
unsigned int j;
forj=400; j0; j--;
}
void init
{
clr_lcden;
write_com0x38;
delay5ms;
write_com0x0c;
delay5ms;
write_com0x06;
delay5ms;
write_com0x01;
}
void lcd_posunsigned char x,unsigned char y
{
dataport=0x80 0x40*x y;
P1DIR|=BIT3 ;
P1DIR|=BIT5 ;
P2DIR=0xff;
clr_rs;
clr_lcden;
delay5ms;
delay5ms;
set_lcden;
delay5ms;
clr_lcden;
}
void displayunsigned long int num
{
uchar k;
uchar dis_flag=0;
uchar table[7];
ifnum0
{
dis_flag=1;
table[0]=num%10 ''0'';
}
else ifnum9
{
dis_flag=2;
table[0]=num10 ''0'';
table[1]=num%10 ''0'';
}
else ifnum99
{
dis_flag=3;
table[0]=num100 ''0'';
table[1]=num10%10 ''0'';
table[2]=num%10 ''0'';
}
else ifnum999
{
dis_flag=4;
table[0]=num1000 ''0'';
table[1]=num100%10 ''0'';
table[2]=num10%10 ''0'';
table[3]=num%10 ''0'';
}
fork=0; k
delay5ms;
}
}
void dispunsigned char *s
{
while*s 0
{
write_date*s;
s;
}
}
void main
{
WDTCTL = WDTPW WDTHOLD; 关闭看门狗
int_clk;
dataout;
init;
P1DIR|=BIT3 BIT5;
DS18B20_DQ_H;
SDAOUT;
while1
{
Read_18B20_Temperature1;
lcd_pos0,0;
disptab;
lcd_pos0,6;
displayTem_dispbuf[4];
write_date''.'';
displayTem_dispbuf[0];
write_date0xdf;
write_date''C'';
delay_us500;
}
}
效果图如图318所示。
图318基于单片机的温度检测控制系统设计效果图
3.6温湿度传感器的设计设计要求: 由温湿度传感器DHT11检测的环境温度及湿度信号送入单片机,通过12864显示出环境温度和湿度并校验。显示环境温湿度的设计关键是温湿度传感器DHT11的应用,DHT11与DS18B20的功能类似,均通过单线制串行接口与单片机进行数据传输,两者对于时序要求也相当严格。DHT11工
图319DHT11引脚图
作原理是先由单片机发送一个复位脉冲,释放总线并进入接收状态,在检测到单片机发出的上升沿后发送一个低电平返回主机,初始化完成。此后,由低功耗模式转变为高速模式,将所测量的40Bit数据送回单片机内部,测量完成。DHT11是具有自校验功能的数字信号输出的温湿度复合信号传感器,信号具有极高的稳定性,传输距离可达将近20m,内部自带自校验功能,是在没有温湿度标准下用来判断所测数据是否正确的一个重要的评判标准。其引脚图如图319所示。
DHT11芯片引脚简介: 引脚1VCC: 连接单片机电源,工作电压为3.3~5V,最大不超过5.5V; 引脚2DATA: 数据传送口,单总线制,串口一共向单片机发送5组8位二进制数据,具体形式为: 温度高8位 温度低8位 湿度高8位 湿度低8位 校验8位,其中低8位数值默认值为0; 引脚3悬空,有的元器件无此引脚; 引脚4GND: 与单片机的电源地相连。
温湿度传感器的相关的时序如图320所示。
图320DHT11芯片时序图
图320为DHT11整体的通讯时序图。首先,在空闲状态下,DATA为高电平,单片机发送开始信号,主机拉低总线至少18ms,然后又拉高总线20~40s,再等待DHT11响应,过程为DHT11把总线拉低80s,再拉高总线80s后就开始传输数据。具体时序如图321所示。
图321时序图
综上所述,DHT11对时序要求比较严格,这是正确接收DHT11数据的关键。数据一共五组,每组数据为8位二进制数。对于每位的数据,都相隔有50s低电平间隙,高电平的时间长短决定了数据是0还是1。如果高电平的时间为26~28s,那么就是0,如果高电平的时间约为70s,那么就是1。采集数据完成后,数据发送返回单片机芯片存储。数字0和数字1信号如图322、图323所示。
图322数字0的表示
图323数字1的表示
上述所提及的关键延时如18ms、80s以及50s是编写传感器DHT11的关键,如果不能确定程序的延时是否正确,可以先编写延时函数,通过示波器观测,修改延时函数符合要求后加入程序中。本程序中delay_usx和delay_msx是非常精确的,直接调用即可。那么在程序中如何判断接收的数据是1还是0?从图321可以看出,DHT11拉高总线80s后有50s的低电平,这段50s时间可以用语句while!D7_R表示,当进入高电平时,再延时40s,从图322和图323可以看出,如果此时采样的数值是低电平,那么该位就是0; 如果此时采样的数值为高电平,那么该位就是1。循环8次,就把一个字节的数值读出来。这样重复5次,依次读出温度高8位,温度低8位都是0,湿度高8位,湿度低8位都是0以及校验和。如果温度数值与湿度数值之和等于校验和,就说明温湿度传感器输出数据正确。基于单片机的温湿度传感器的电路图如图324所示。
图324基于单片机的温湿度传感器电路图
#include
#define CPU_F double8000000
#define delay_usx __delay_cycleslongCPU_F*doublex1000000.0
#define delay_msx __delay_cycleslongCPU_F*doublex1000.0
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
#define D7_IN P1DIR&=~BIT7
#define D7_OUT P1DIR|=BIT7 D7口设置为输出
#define D7_CLR P1OUT&=~BIT7 输出0
#define D7_SET P1OUT|=BIT7 输出1
#define D7_R P1IN&0x80读
#define SID BIT1
#define SCLK BIT2
#define CSBIT0
#define LCDPORT P3OUT
#define SID_1 LCDPORT |= SID SID置高P3.1
#define SID_0 LCDPORT &= ~SIDSID置低
#define SCLK_1 LCDPORT |= SCLKSCLK置高P3.2
#define SCLK_0 LCDPORT &= ~SCLKSCLK置低
#define CS_1LCDPORT |= CS CS置高P3.0
#define CS_0LCDPORT &= ~CS CS置低
uchar dis_flag,k,U8FLAG,U8cont,U8temp,
U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,t,i,
U8checkdata,U8comdata,U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
#define SCL_H P3OUT|=BIT3
#define SCL_L P3OUT&=~BIT3
#define SDA_H P3OUT|=BIT1
#define SDA_L P3OUT&=~BIT1
#define SCL_read P3IN&BIT3
#define SDA_read P3IN&BIT1
uchar table[7]="";
uchar tab0[]={"温湿度检测系统"};
uchar tab1[]={"温度: "};
uchar tab2[]={"湿度"};
uchar tab3[]={"校验和"};
void Clk_Init
{
unsigned char i;
BCSCTL1&=~XT2OFF;打开XT2振荡器
BCSCTL2|=DIVS0 DIVS1;MCLK为8MHz, SMCLK为8MHz
BCSCTL2|=SELM1 SELS;
do
{
IFG1 &= ~OFIFG;清除振荡错误标志
fori=0; i0; i--
forj=120; j0; j--;
}
void sendbyteuchar zdata 数据传送函数
{
uint i;
fori=0; i0
{
write_dat*S;
S;
}
}
void displayint num
{
ifnum=0
{
dis_flag=1;
table[0]=num%10 ''0'';
fork=0; k9
{
dis_flag=2;
table[0]=num10 ''0'';
table[1]=num%10 ''0'';
fork=0; k99
{
dis_flag=3;
table[0]=num100 ''0'';
table[1]=num10%10 ''0'';
table[2]=num%10 ''0'';
fork=0; k999
{
dis_flag=4;
table[0]=num1000 ''0'';
table[1]=num100%10 ''0'';
table[2]=num10%10 ''0'';
table[3]=num%10 ''0'';
fork=0; k
#define CPU_F double8000000
#define delay_usx __delay_cycleslongCPU_F*doublex1000000.0
#define delay_msx __delay_cycleslongCPU_F*doublex1000.0
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
#define HX P4OUT
#define HX711_DOUT0 HX&0Xef
#define HX711_DOUT1 HX|0X10
#define HX711_SCK0 HX&0Xdf
#define HX711_SCK1 HX|0X20
#define SID BIT1
#define SCLK BIT2
#define CSBIT0
#define LCDPORT P3OUT
#define SID_1 LCDPORT |= SID SID置高P3.1
#define SID_0 LCDPORT &= ~SIDSID置低
#define SCLK_1 LCDPORT |= SCLKSCLK置高P3.2
#define SCLK_0 LCDPORT &= ~SCLK SCLK置低
#define CS_1LCDPORT |= CS CS置高P3.0
#define CS_0LCDPORT &= ~CSCS置低
int shu8;
uchar keyvalue,lcd_bus;
uchar table[ ];
uchar dis2[ ]={"重量:"};
uchar dis3[ ]={"单价:"};
uchar dis4[ ]={"总价:"};
uchar dis5[ ]={"元"};
uchar dis6[ ]={"克"};
int num=0;
int i,j;
void int_clk
{
unsigned char i;
BCSCTL1&=~XT2OFF; 打开XT振荡器
BCSCTL2|=SELM1 SELS; MCLK为8MHz,SMCLK为1MHz
do
{
IFG1&=~OFIFG; 清除振荡器错误标志
fori=0;i0;i--
forj=120;j0;j--;
}
void sendbyteuchar zdata 数据传送函数
{
fori=0;i0
{
write_dat*S;
S;
}
}
void displayint num
{
uchar k;
uchar dis_flag=0;
uchar table[7];
ifnum=0
{
dis_flag=1;
table[0]=num%10 ''0'';
}
else ifnum9
{
dis_flag=2;
table[0]=num10 ''0'';
table[1]=num%10 ''0'';
}
else ifnum99
{
dis_flag=3;
table[0]=num100 ''0'';
table[1]=num10%10 ''0'';
table[2]=num%10 ''0'';
}
else ifnum999
{
dis_flag=4;
table[0]=num1000 ''0'';
table[1]=num100%10 ''0'';
table[2]=num10%10 ''0'';
table[3]=num%10 ''0'';
}
fork=0;k
delay_ms5;
}
}
uchar keyscanvoid
{
P5OUT=0xef;
ifP5IN&0x0f!=0x0f
{
delay_us100;
ifP5IN&0x0f!=0x0f
{
ifP5IN&0x01==0
keyvalue=1;
ifP5IN&0x02==0
keyvalue=2;
ifP5IN&0x04==0
keyvalue=3;
ifP5IN&0x08==0
keyvalue=4;
whileP5IN&0x0f!=0x0f;
}
}
P5OUT=0xdf;
ifP5IN&0x0f!=0x0f
{
delay_us100;
ifP5IN&0x0f!=0x0f
{
ifP5IN&0x01==0
keyvalue=5;
ifP5IN&0x02==0
keyvalue=6;
ifP5IN&0x04==0
keyvalue=7;
ifP5IN&0x08==0
keyvalue=8;
whileP5IN&0x0f!=0x0f;
}
}
P5OUT=0xbf;
ifP5IN&0x0f!=0x0f
{
delay_us100;
ifP5IN&0x0f!=0x0f
{
ifP5IN&0x01==0
keyvalue=9;
ifP5IN&0x02==0
keyvalue=0;
ifP5IN&0x04==0
keyvalue=10;
ifP5IN&0x08==0
keyvalue=11;
whileP5IN&0x0f!=0x0f;
}
}
P5OUT=0x7f;
ifP5IN&0x0f!=0x0f
{
delay_us100;
ifP5IN&0x0f!=0x0f
{
ifP5IN&0x01==0
keyvalue=12;
ifP5IN&0x02==0
keyvalue=13;
ifP5IN&0x04==0
keyvalue=14;
ifP5IN&0x08==0
keyvalue=15;
whileP5IN&0x0f!=0x0f;
}
}
return keyvalue;
}
int HX711_Readvoid增益128
{
unsigned long count=0;
count=count&0x0000000;第25个脉冲下降沿来时,转换数据
P4DIR|=0xef;
HX=HX711_DOUT1; 数据口
delay_us4;
HX=HX711_SCK0; 控制口
whileP4IN&0X10==0X10;
delay_us40;
forj=0;j
displayshu2;
write_cmd0x97;
fornum=0;num

 

 

書城介紹  | 合作申請 | 索要書目  | 新手入門 | 聯絡方式  | 幫助中心 | 找書說明  | 送貨方式 | 付款方式 香港用户  | 台灣用户 | 大陸用户 | 海外用户
megBook.com.hk
Copyright © 2013 - 2024 (香港)大書城有限公司  All Rights Reserved.