《大学毕设论文--基于can总线的温湿度及光感度测量--单片机课程设计.doc》由会员分享,可在线阅读,更多相关《大学毕设论文--基于can总线的温湿度及光感度测量--单片机课程设计.doc(53页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、基于CAN总线的温湿度及光感度测量单片机系统课程设计报告 专 业:组 员:指 导 教 师:完成日期:2013 年 7 月 11 日基于CAN总线的温湿度及光感度测量摘要:随着我国工业生产的发展和自动化程度的不断提高,迫切需要对各种生产过程中的物理量进行精确检测。温度、湿度作为大多数生产过程中的重要物理量,对它们的精确检测和远传越来越受到人们重视。因此,研制一种高精度、高稳定性、低成本的温湿度仪表将具有重要意义,必将拥有广阔的市场前景。同时,由于工业现场对抗电磁干扰和传输距离有比较高的要求,所以本文设计了一种基于CAN(ControlArea Network局域网控制)总线的远程实时温湿度数据采
2、集系统。该系统主要由两大模块构成,分别是数据现场采集模块、和显示处理模块。本设计使用C语言进行了各个模块软件的设计,完成对传感器信号的处理和CAN模块报文的发送和接收。关键词:430 CAN DHT11 温湿度 光感度1设计方案论证1.1主控芯片选择(1) 用可编程逻辑器件设计。可采用ALTERA公司的FLEX10K系列PLD器件。设计起来结构清晰,各个模块,从硬件上设计起来相对简单,控制与显示的模块间的连接也会比较方便。但是考虑到本设计的特点,EDA在功能扩展上比较受局限,而且EDA占用的资源也相对多一些。从成本上来讲,用可编程逻辑器件来设计也没有什么优势。(2) 用MSP430F149作主
3、控芯片,编程简单,功能丰富,速度很快,功耗很低。因此选择430作为数据采集和显示处理的主控芯片。2显示部分的方案选择(1) 数码管显示方式采用八段数码管经济实惠,亮度高,对比度高,显示清晰;但操作很复杂,占用很多CPU时间。(2) 液晶显示方式 液晶显示效果出众,操作简单,输入完显示信息后不占用CPU时间,显示容量也大,因此采用1602液晶显示器。3传感器选择(1) 采用DS18B20数字温度传感器,精度高,灵敏度高;但不能采集湿度信息;(2) 采用DHT11数字温度传感器,可同时测量温度和湿度,精度和灵敏度,转换速度也都能满足本次系统要求,而且DHT11采用单总线通信模式,占用IO口少。因此
4、选用DHT11数字温湿度传感器。2系统设计采用MSP430F149作为数据采集和接收处理显示模块的主控芯片,430和各种传感器通信读出各种测量参数,通过CAN控制器将信息发送到CAN 总线上;数据接收模块从CAN总线上读取各种信息并通过显示模块显示出来。传感器数据采集数据接收显示模块CAN总线图1 远程温湿度数据采集3单元电路设计3.1温湿度采集系统DHT11数字温湿度传感器BH1750FVI环境光强度传感器MSP430F149SJA1000CAN控制器TJAl050收发器CAN BUS图2 远程温湿度数据采集模块由图2所示,温湿度数据采集模块的硬件由以下四部分构成:传感器DHT11,微控制器
5、MSP430F149,CAN控制器和CAN收发器。微控制器MSP430F149主要负责对传感器输出的两路模拟信号进行循环采集并AD转换,SJAl000的初始化,通过控制JAl000实现数据的发送和接收。SJAl000负责数据链路层的工作,把发送缓冲器的数据经过处理后送到TJAl050,信息经过处理后放到接收缓冲器等待微处理器的读取。TJA1050提供SJA1000与物理总线之间的接口。3.2数据处理显示模块SJA1000CAN控制器TJAl050收发器CAN BUS图3数据接收处理显示模块MSP430F149EnC/SR/W1602液晶显示器如图3所示TJA1050收发器将信号差分放大去除噪声
6、后送给SJA1000控制器,控制器将接到的报文处理后提取数据给430,430将数据显示到1602显示器上。4系统功能本文设计的系统能实时测量远程温湿度及光强度。测量范围:温度050,湿度2090%RH,光强1lx-65535lx;分辨率:温度1,湿度+/-2,光强1lx;测量距离:1km5程序模块流程图开始初始化系统初始化SJA1000是否中断接收一个字节数据转存开始初始化系统初始化SJA1000是否发完发送一个字节图4 数据接收模块程序流程图图5 数据发送模块程序流程图参考文献1 李正军编著现场总线及其应用技术M北京机械工业出版社200512 任广永等基于AT89C55和CAN总线的远程数据
7、采集系统的设计J电脑学习200723 潘琢金,施国君C8051FXXX高速SOC单片机原理及应用M北京:北京航空航天大学出版社20024吴文珍,韩玉祥,司光宇等基于CAN总线智能检测仪的设计D大庆石油学院学报2005,29(5)5SJAl000独立CAN控制器数据手册广州周立功单片机发展有限公司心得体会谢广昊:通过此次课程设计,使我更加扎实的掌握了有关CAN总线方面的知识,在设计过程中虽然遇到了一些问题,但经过一次又一次的思考,一遍又一遍的检查终于找出了原因所在,也暴露出了前期我在这方面的知识欠缺和经验不足。实践出真知,通过亲自动手制作,使我们掌握的知识不再是纸上谈兵。过而能改,善莫大焉。在课
8、程设计过程中,我们不断发现错误,不断改正,不断领悟,不断获取。最终的检测调试环节,本身就是在践行“过而能改,善莫大焉”的知行观。这次课程设计终于顺利完成了,在设计中遇到了很多问题,最后在老师的指导下,终于游逆而解。在今后社会的发展和学习实践过程中,一定要不懈努力,不能遇到问题就想到要退缩,一定要不厌其烦的发现问题所在,然后一一进行解决,只有这样,才能成功的做成想做的事,才能在今后的道路上劈荆斩棘,而不是知难而退,那样永远不可能收获成功,收获喜悦,也永远不可能得到社会及他人对你的认可!马少波:我认为,在这学期的实验中,不仅培养了独立思考、动手操作的能力,在各种其它能力上也都有了提高。更重要的是,
9、在实验课上,我们学会了很多学习的方法。而这是日后最实用的,真的是受益匪浅。要面对社会的挑战,只有不断的学习、实践,再学习、再实践。这对于我们的将来也有很大的帮助。以后,不管有多苦,我想我们都能变苦为乐,找寻有趣的事情,发现其中珍贵的事情。就像中国提倡的艰苦奋斗一样,我们都可以在实验结束之后变的更加成熟,会面对需要面对的事情。回顾起此课程设计,至今我仍感慨颇多,从理论到实践,在这段日子里,可以说得是苦多于甜,但是可以学到很多很多的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有
10、把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,但可喜的是最终都得到了解决。张巨龙:回顾起此次单片机课程设计,至今我仍感慨颇多,的确,从选题到定稿,从理论到实践,在整整两星期的日子里,可以说得是苦多于甜,但是可以学到很多很多的的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动
11、手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,这毕竟第一次做的,难免会遇到过各种各样的问题。最后在老师的辛勤指导下,终于游逆而解。同时,在老师的身上我学得到很多实用的知识,在次我表示感谢!同时,对给过我帮助的所有同学和各位指导老师再次表示忠心的感谢!附录一元件清单器件数量MSP430F149 芯片2SAJ1000CAN控制器2BH1750光强度传感器1DHT11温湿度传感器11602液晶显示器1排线5*8=40排针5*8=40电阻2K4红色发光二级管4BUTTON(复位开关)2附录二系统程序清单Main.c#include#include SJA1000.h#includ
12、e DHT11.h#include BH1750.h#include IIC.h/*精确延时*#define CPU_F (double)8000000)#define delay_us(x) _delay_cycles(long)(CPU_F*(double)x/1000000.0)#define delay_ms(x) _delay_cycles(long)(CPU_F*(double)x/1000.0)/*#define uint unsigned int#define uchar unsigned char#define rcv_flag 0x01 /接收中断标志#define err
13、_flag 0x02 /错误中断标志#define Over_flag 0x04 /CAN总线超载标志void Init_BH1750(); /BH1750初始化void SJA_Process(void);void init_CPU (void); /初始化MSP430uchar send_flag = 0; /CAN总线发送标志unsigned char Can_INT_DATA=0; /用于存储SJA1000的中断寄存器数据,430中不能位寻址 /-uchar rcv_data10; /接收数据数组 /-void main( void ) WDTCTL = WDTPW + WDTHOLD
14、; / Stop watchdog timer to prevent time out reset uchar SJA_status; init_CPU (); /初始化MSP430 Init_BH1750(); /初始化BH1750 do delay_ms(10); /小延时 SJA_status = init_SJA1000 (); while(SJA_status); /初始化SJA1000 Can_INT_DATA=0; /CAN中断变量清零 delay_ms(1000); _EINT(); /开总中断 while(1) uchar Read_BUF2 = 0,0; /读回BH1750
15、数据变量 read_TRH(); /读取温湿度传感器 delay_ms(120); Read_1Byte_currentaddress(Read_BUF); /读回BH1750数据 send_data6 = Read_BUF0; send_data7 = Read_BUF1; send_flag = 1; SJA_Process();/SJA最终处理 /*函数原型:void Init_BH1750();函数功能:BH1750初始化*/void Init_BH1750() Write_1Byte(0x01); /通电,等待测量指令 Write_1Byte(0x07); /通电后,重置数字寄存器
16、Write_1Byte(0x10); /连续H分辨率模式/*函数功能:SJA_1000最终处理函数*/void SJA_Process(void) if(Can_INT_DATA & rcv_flag)=rcv_flag )/接收中断 Can_INT_DATA &= rcv_flag; /清除接收标志位 SJA_rcv_data(rcv_data); /接收CAN总线数据到rcv_data数组 if(send_flag)/发送中断 send_flag=0; /清除发送标志位 SJA_send_data(send_data); /把send_data数组中数据写入到发送缓冲区 if(Can_IN
17、T_DATA & Over_flag)=Over_flag)/溢出中断 Can_INT_DATA &= Over_flag; /清除溢出标志位 Can_DATA_OVER(); if(Can_INT_DATA & err_flag)=err_flag )/错误中断 Can_INT_DATA &= err_flag; /清除错误标志位 Can_error(); /*函数功能:初始化MSP430*/void init_CPU (void) /*下面六行程序关闭所有的IO口*/ P1DIR = 0XFF;P1OUT = 0XFF; P2DIR = 0XFF;P2OUT = 0XFF; P3DIR =
18、 0XFF;P3OUT = 0XFF; P4DIR = 0XFF;P4OUT = 0XFF; P5DIR = 0XFF;P5OUT = 0XFF; P6DIR = 0XFF;P6OUT = 0XFF; /P6DIR |= BIT2;P6OUT &= BIT2; /打开电平转换 / P2DIR |= BIT3;P2OUT &= BIT3; /电平转换方向3.3V-5V /-P1.7外部中断-/ P1DIR &= BIT7; /设置P1.7为输入 P1IES |= BIT7; /设置为下降沿中断 P1IE |= BIT7; /允许P1.7中断 /-/ /-切换时钟-/ unsigned int j
19、; BCSCTL1 &= XT2OFF; / XT2on, max RSEL do IFG1 &=OFIFG; for(j=0xff;j0;j-); while(IFG1&OFIFG); BCSCTL2 |= SELS+DIVS_0; /SMCLK = XT2;SMCLK=8MHZ BCSCTL2 |= SELM_2+DIVM_0; /MCLK = XT2;MCLK=8MHZ /-*/ /-定时器设置-/ /* TACCTL0 = CCIE; /使能CCR0中断 CCR0 = 2048; /设定周期1S TACTL = TASSEL_1 + ID_3 + MC_1;/定时器A的时钟源选择ACL
20、K,增计数模式 _EINT(); /开总中断*/ /-/#pragma vector=PORT1_VECTOR /P1口中断源_interrupt void P1_ISR(void) /中断名P1_ISR(void) if(P1IFG & BIT7) Can_INT_DATA = Read_Reg(INTERRUPT); P1IFG = 0;SJA1000.c#include#include SJA1000.h/*精确延时*#define CPU_F (double)8000000)#define delay_us(x) _delay_cycles(long)(CPU_F*(double)x/
21、1000000.0)#define delay_ms(x) _delay_cycles(long)(CPU_F*(double)x/1000.0)/* uchar send_data10; /发送数据数组/*函数原型:unsigned char Read_Reg(unsigned char reg)函数功能:读取SJA1000寄存器中的值参数说明:reg:寄存器地址 */unsigned char Read_Reg(unsigned char reg) unsigned char Reg_Data; C_ALE; S_RD; S_WR; S_CS; S_ALE; _NOP(); PortDIR
22、=0xff; /P2OUT &= BIT3; /电平转换方向3.3V-5V PortOUT = reg; _NOP(); C_ALE; _NOP(); C_CS; _NOP(); C_RD; _NOP();_NOP(); / P2OUT |= BIT3; /电平转换方向5V-3.3V PortDIR=0x00; Reg_Data=PortIN; S_RD; _NOP(); S_CS; return Reg_Data;/*函数原型:void Write_Reg(unsigned char reg,unsigned char reg_data)函数功能:向SJA1000寄存器中写值参数说明: re
23、g:寄存器地址 reg_data:要写入的值*/void Write_Reg(unsigned char reg,unsigned char reg_data) C_ALE; S_CS; S_RD; S_WR; S_ALE; _NOP(); /P2OUT &= BIT3; /电平转换方向3.3V-5V PortDIR =0xff; PortOUT = reg; _NOP(); C_ALE; _NOP(); C_CS; _NOP(); C_WR; _NOP(); PortOUT= reg_data; _NOP(); _NOP(); S_WR; _NOP(); S_CS; _NOP(); _NOP
24、(); S_ALE;/*函数原型:char create_communication(void)函数功能:用于SJA1000在复位模式下,检测CAN控制器SJA1000的通信是否正常,只用于产品 的测试,如果在正常模式下使用这个寄存器进行测试,将导致设备不可预测的结果。返回值说明: 0:表示SJA1000建立通信正常 1:表示SJA1000与处理器通信异常*/char create_communication(void) Write_Reg(TEST,0xaa); /向TEST寄存器中写入0xaa if(Read_Reg(TEST) = 0xaa) return 0; /读测试正确 else
25、return 1;/*函数原型:char enter_RST(void)函数功能:用于SJA1000进入复位工作模式返回值说明: 0:表示SJA1000成功进入复位工作模式 1:表示SJA1000进入复位模式失败*/char enter_RST(void) unsigned char MID_DATA; /定义一个字节变量,用于存储从SJA1000控制寄存器读出的数据 MID_DATA = Read_Reg(CONTROL);/访问SJA1000控制寄存器,保存原始值 Write_Reg(CONTROL,MID_DATA|0x01); /置位复位请求 if(Read_Reg(CONTROL)&
26、0x01)=1) /读SJA1000的控制寄存器数值,判断复位请求是否有效 return 0; /表示SJA1000成功进入复位工作模式 else return 1; /*函数原型:char quit_RST(void)函数功能:用于SJA1000退出复位工作模式返回值说明: 0:表示SJA1000成功退出复位工作模式 1:表示SJA1000退出复位模式失败*/char quit_RST(void) unsigned char MID_DATA; /定义一个字节变量,用于存储从SJA1000控制寄存器读出的数据 MID_DATA = Read_Reg(CONTROL);/访问SJA1000控制
27、寄存器,保存原始值 Write_Reg(CONTROL,MID_DATA&0xfe); /置位复位请求 if(Read_Reg(CONTROL)&0x01)=0) /读SJA1000的控制寄存器数值,判断清除复位请求是否有效 return 0; /0:表示SJA1000成功退出复位工作模式 else return 1; /*函数原型:char set_rate(unsignen char CAN_rate_num)函数功能:用于设置CAN总线的通信波特率,只能在SJA1000进入复位模式下使用参数说明:参数CAN_rate_num用于存放CAN通信波特率的数组列表中的系列号,范围为012.返回
28、值说明: 0:波特率设置成功 1:波特率设置失败*/unsigned char rate_tab= 0x53,0x2f, /20kbit/s的波特率预设值 0x87,0xff, /40kbit/s 0x47,0x2f, /50kbit/s 0x83,0xff, /80kbit/s 0x43,0x2f, /100kbit/s 0x03,0x1c, /125kbit/s 0x81,0xfa, /200kbit/s 0x01,0x1c, /250kbit/s 0x80,0xfa, /400kbit/s 0x00,0x1c, /500kbit/s 0x80,0xb6, /666kbit/s 0x00,
29、0x16, /800kbit/s 0x00,0x14 /1000kbit/s;/-char set_rate (unsigned char CAN_rate_num) char wrong_flag=1; unsigned char BIT0_data,BIT1_data; /用于存放从波特率数组中读出来的数值 unsigned char wrong_count=32; /32次报错次数 if(CAN_rate_num12) /设置数组列表中的序列号范围为012 wrong_flag=1; /如果超出范围,报警,波特率设置失败 else while(-wrong_count) /最多32次设置
30、SJA1000内部寄存器BIT0和BIT1 BIT0_data=rate_tabCAN_rate_num*2; BIT1_data=rate_tabCAN_rate_num*2+1;/将波特率的设置值从数组中读出 Write_Reg(BIT_0,BIT0_data);/访问CAN总线定时寄存器0,写入参数 if(Read_Reg(BIT_0) != BIT0_data )continue; /校验写入值 Write_Reg(BIT_1,BIT1_data);/访问CAN总线定时寄存器1,写入参数 if(Read_Reg(BIT_1) != BIT1_data )continue; /校验写入值
31、 wrong_flag = 0; break; /while 结束 return wrong_flag;/*函数原型:char set_ACR_AMR(unsignen char ACR_DATA,unsignen char AMR_DATA)函数功能:用于设置验收代码寄存器(ACR),屏蔽寄存器(AMR)只能在SJA1000进入复位模式下使用参数说明:ACR_DATA :用于存放验收代码寄存器(ACR)的参数值 AMR_DATA :用于存放验收代码寄存器(AMR)的参数值返回值说明: 0:通信对象设置成功 1:通信对象置失败*/char set_ACR_AMR(unsigned char A
32、CR_DATA,unsigned char AMR_DATA) /滤波器设计 Write_Reg(ACR,ACR_DATA);/访问CAN总线验收代码寄存器,写入参数 if(Read_Reg(ACR) != ACR_DATA)/校验写入值 return 1; Write_Reg(AMR,AMR_DATA);/访问CAN总线验收代码寄存器,写入参数 if(Read_Reg(AMR) != AMR_DATA)/校验写入值 return 1; return 0;/*函数原型:char set_CLK (unsigned char SJA_OUT_MODE,unsigned char SJA_Cloc
33、k_Out)函数功能:用于设置输出寄存器(OCR)的参数、时钟分频寄存器(CDR)的参数, 只能在SJA1000进入复位模式下使用参数说明:SJA_OUT_MODE :用于存放输出寄存器(OC)的参数 SJA_Clock_Out :用于存放时钟分频寄存器(CDR)的参数返回值说明: 0:设置(OCR)和(CDR)寄存器成功 1:设置(OCR)和(CDR)寄存器失败*/char set_CLK (unsigned char SJA_OUT_MODE,unsigned char SJA_Clock_Out) Write_Reg(OCR,SJA_OUT_MODE);/访问输出控制寄存器,写入设置的O
34、CR参数值 if(Read_Reg(OCR) != SJA_OUT_MODE)/校验写入值 return 1; Write_Reg(CDR,SJA_Clock_Out);/访问输出控制寄存器,写入设置的CDR参数值 / if(Read_Reg(CDR) != SJA_Clock_Out)/校验写入值 / return 1; return 0;/*函数原型:char SJA_send_data(unsigned char *senddatabuf)函数功能:用于发送CAN总线一帧数据(数据帧或远程帧)到SJA1000的发送缓冲区, 数据帧长度不大于8字节参数说明:senddatabuf :指向的
35、用于存放发送数据的数组的首址 返回值说明: 0:将发送数组的数据成功送至SJA1000的发送区 1:SJA1000正在接收信息,或SJA1000的发送缓冲区被锁定, 或上一次发送的一帧数据还没有完成发送*/char SJA_send_data(unsigned char *senddatabuf) /gai! unsigned char send_num,STATUS_data; unsigned char i; STATUS_data = Read_Reg(STATUS);/读取状态寄存器数值到STATUS_data if(STATUS_data & 0x10) return 1; /STATUS_data4,表示SJA1000在接收信息 if(STATUS_data & 0x04)=0)/判断SJA1000发送缓冲区是否为锁定状态,0锁定 return 1; if(STATUS_data & 0x08)=0)/判断上次发送是否完成,0上次发送未完成