1 / 48

第四章 C51 程序设计 -2 实例

第四章 C51 程序设计 -2 实例. 开题报告第 6 , 9 , 10 , 12 还没有发给齐老师,明天下午 5 : 00 之前必须交给齐老师。. 1-wire 总线及应用. 一根数据线。设备(主机或从机)通过一个漏极开路端口,连接至该数据线,这样允许设备在不发送数据时释放数据总线,以便总线被其它设备所使用。 1-wire 总线端口为漏极开路,单总线要求外接一个约 5k 的上拉电阻,这样单总线的闲置状态为高电平。 主机对 1-Wire 总线的基本操作分为复位、读和写三种,其中所有的读写操作均为低位在前,高位在后。 典型的单总线命令序列 第一步 初始化;

tobit
Download Presentation

第四章 C51 程序设计 -2 实例

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第四章 C51程序设计-2实例 开题报告第6,9,10,12还没有发给齐老师,明天下午5:00之前必须交给齐老师。

  2. 1-wire总线及应用 • 一根数据线。设备(主机或从机)通过一个漏极开路端口,连接至该数据线,这样允许设备在不发送数据时释放数据总线,以便总线被其它设备所使用。 1-wire总线端口为漏极开路,单总线要求外接一个约5k 的上拉电阻,这样单总线的闲置状态为高电平。 • 主机对1-Wire总线的基本操作分为复位、读和写三种,其中所有的读写操作均为低位在前,高位在后。 • 典型的单总线命令序列 • 第一步 初始化; • 第二步 ROM 命令 跟随需要交换的数据; • 第三步 功能命令 跟随需要交换的数据;

  3. 实例:DS18B20单线温度传感器 • 主要特征 • 全数字温度转换及输出。 • 1-wire总线数据通信。 • 最高12位分辨率,精度可达土0.5摄氏度。 • 12位分辨率,最大工作周期为750毫秒。 • 检测温度范围为-55℃~+125℃。 • 内置EEPROM,限温报警功能。 • 64位光刻ROM,内置产品序列号,方便多机挂接。 • 多样封装形式,适应不同硬件系统。

  4. DS18B20工作原理 • 三种形态的存储器资源 • ROM 只读存储器,用于存放DS18B20ID编码。 • RAM 数据暂存器,用于内部计算和数据存取,数据在掉电后丢失,DS18B20共9个字节RAM,每个字节为8位。 • EEPROM 非易失性记忆体,用于存放长期需要保存的数据,上下限温度报警值和校验数据。 • RAM及EEPROM 结构图:

  5. 控制器对18b20操作流程 • 复位:给DS18B20单总线至少480uS的低电平信号。 • 存在脉冲:复位电平结束之后,控制器应该将数据单总线拉高,以便于在15~60uS后接收存在脉冲,存在脉冲为一个60~240uS的低电平信号。 • 控制器发送ROM指令:ROM指令共有5条,每一个工作周期只能发一条,ROM指令分别是读ROM数据、指定匹配芯片、跳跃ROM、芯片搜索、报警芯片搜索。(一般只挂接单个18B20芯片时可以跳过ROM指令) • 控制器发送存储器操作指令:分别是写RAM数据、读RAM数据、将RAM数据复制到EEPROM、温度转换、将EEPROM中的报警值复制到RAM、工作方式切换。 • 执行或数据读写:一个存储器操作指令结束后则将进行指令执行或数据的读写,这个操作要视存储器操作指令而定。

  6. 几种时间隙 • DS18B20复位及应答关系 • 写时间隙

  7. 读时间隙 注意:必须在读间隙开始的15uS内读取数据位才可以保证通信的正确。 • DS18B20与单片机接法

  8. 示例程序: void Init_DS18B20(void) //18b20初始化 { DQ = 1; //DQ复位 _nop_();_nop_();_nop_(); DQ = 0; //拉低DQ delay(200); //约600us DQ = 1; //拉高总线 delay(20); // 75us,30:100us }

  9. uchar Read_byte(void) //读一字节 { uchar i=0; uchar dat = 0; for (i=8;i>0;i--) { DQ = 1; _nop_();_nop_();_nop_();_nop_(); DQ = 0; //从高拉到低,产生读时间隙 _nop_();_nop_(); //至少保持低电平1us _nop_();_nop_();_nop_();_nop_(); dat>>=1; //右移一位 DQ = 1; //15us内停止将DQ拉低,15us内数据有效 _nop_();_nop_(); //稍作延时 _nop_();_nop_(); if(DQ) //若高电平 置1 dat|=0x80; delay(30); //至少保持60us,100us,确保读数据成功 } DQ = 1; //结束拉高 return(dat); }

  10. void Write_byte(uchar dat) //写一个字节 { uchar i=0; for (i=8; i>0; i--) { DQ = 1; _nop_();_nop_(); //稍作延时 _nop_();_nop_();_nop_();_nop_(); DQ = 0; //拉低DQ开始写 _nop_();_nop_(); _nop_();_nop_(); //15us内释放总线 _nop_();_nop_();_nop_();_nop_(); DQ = dat&0x01; //从lsb开始 delay(20); //75us 至少需保持60us写时间隙 dat>>=1; //右移一位 } DQ = 1; //结束拉高 delay(4); }

  11. uint Get_Temperature(void) //读温度函数 { uchar a=0; uchar b=0; uint t=0; Init_DS18B20(); Write_byte(0xCC); //只接一个18b20芯片,skip ROM Write_byte(0x44); //温度转换 delay(200); //延时600us 等待转换完成,一般转换时间为500us Init_DS18B20(); Write_byte(0xCC); //skip ROM Write_byte(0xBE); //从RAM读数据 a=Read_byte(); //先读低位 b=Read_byte(); //再读高位 t=b<<8; t=t|a; //t为最后读得的数据 return (t); }

  12. 双向二线制串行通信总线,时钟线SCL, 数据线SDA。 NXP 半导体(原Philips 半导体)于20 多年前发明。 I2C总线是同步串行数据传输总线。 经常使用的带I2C总线通用外围器件有:SRAM、E2PROM、ADC/DAC、RTC、I/O口等。 带I2C总线的外围设备模块有由LED驱动控制器构成的LED显示器,由各种LCD驱动控制器构成的段式、字符点阵、图形点阵液晶显示器等。 I2C总线及应用

  13. I2C 总线的信号线 I2C 总线只需要由两根信号线组成,一根是串行数据线SDA,另一根是串行时钟线SCL,均为为开漏结构,故总线上必须有上拉电阻Rp,通常可选5~10kΩ。

  14. I2C总线时序定义: 起始条件和停止条件(START and STOP conditions) 起始条件:当SCL 处于高电平期间时,SDA 从高电平向低电平跳变时产生起始条件。总线在起始条件产生后便处于忙的状态。起始条件常常简记为S。 停止条件:当SCL 处于高电平期间时,SDA 从低电平向高电平跳变时产生停止条件。总线在停止条件产生后处于空闲状态。停止条件简记为P。

  15. I2C 总线上数据的有效性(Data validity) 数据线SDA 的电平状态必须在时钟线SCL 处于高电平期间保持稳定不变。SDA 的电平状态只有在SCL 处于低电平期间才允许改变。但是在I2C 总线的起始和结束时例外。

  16. 从机地址(Slave Address) I2C 总线不需要地址译码器和片选信号。多个具有I2C 总线接口的器件都可以连接到同一条I2C 总线上,它们之间通过器件地址来区分。 主机是主控器件,它不需要器件地址,其它器件都属于从机,要有器件地址。必须保证同一条I2C 总线上所有从机的地址都是唯一。 一般从机地址由7 位地址位和一位读写标志R/W 组成,7 位地址占据高7 位,读写位在最后。读写位是0,表示主机将要向从机写入数据;读写位是1,则表示主机将要从从机读取数据。 从机地址由一个固定和一个可编程的部分构成。从机地址的可编程部分使最大数量的相同器件可以连接到I2C 总线上,器件可编程地址位的数量由管脚决定,如果器件3 个可编程的地址管脚,那么I2C总线上共可以连接8 个相同的器件。

  17. I2C数据传输的方式 以字节(Byte)为单位收发数据。首先传输的是数据的最高位(MSB,第7 位),最后传输的是最低位(LSB,第0 位)。另外,每个字节之后还要跟一个响应位,称为应答。 应答(Acknowledge) 每传输一个字节,要跟一个应答状态位。接收器接收数据的情况可通过应答位来告知发送器。应答位的时钟脉冲由主机产生,而应答位的数据状态则遵循“谁接收谁产生”的原则,即总是由接收器产生应答位。主机向从机发送数据时,应答位由从机产生;主机从从机接收数据时,应答位由主机产生。 I2C总线上第9个脉冲对应应答位,SDA为0 表示接收器应答(ACK),A;为1 则表示非应答(NACK),/A。

  18. 基本的数据传输格式 主机向从机发送数据的基本格式 主机从从机接收数据的基本格式 注意:主机向从机发送最后一个字节的数据时,从机可能应答也可能非应答,但不管怎样主机都可以产生停止条件。如果主机在向从机发送数据(甚至包括从机地址在内)时检测到从机非应答,则应当及时停止传输。

  19. 数据传输时序图 主机向从机写数据 (24LC01)

  20. 主机读从机数据(24LC01)

  21. EEPROM —— 24LC01B • 主要特征 • 低至2.5V的单电源供电; • 低功耗的CMOS技术; • 128 bytes(128×8)的存储块; • 标准2线串行接口总线 ,I2C总线; • 兼容100 kHz (2.5V) 、 400kHz (5.0V); • 高达8 bytes的页写入缓存; • 2 ms页写入时间周期; • 硬件写保护。

  22. 硬件电路

  23. I2C通过IO口模拟 void Start(void) //起始信号 { Sda=1; Scl=1; delay1us(); Sda=0; delay1us(); } void Stop(void) //停止 { Sda=0; Scl=1; delay1us(); Sda=1; delay1us(); }

  24. void Ack(void) //应答 { Sda=0; delay1us(); Scl=1; delay1us(); Scl=0; } void NoAck(void) //不应答 { Sda=1; delay1us(); Scl=1; delay1us(); Scl=0; }

  25. void Send(unsigned char Data) //发送字节 { unsigned char xdata BitCounter=8; unsigned char xdata temp; do { temp=Data; Scl=0; delay1us(); if((temp&0x80)==0x80) Sda=1; else Sda=0; delay1us(); Scl=1; delay1us(); temp=Data<<1; //左移1位 Data=temp; BitCounter- -; }while(BitCounter); Scl=0; }

  26. unsigned char Read(void) //读取字节 { unsigned char xdata temp=0; unsigned char xdata temp1=0; unsigned char xdata BitCounter=8; Sda=1; do{ Scl=0; delay1us(); Scl=1; delay1us(); if(Sda) temp=temp|0x01; else temp=temp&0xfe; if(BitCounter-1) { temp1=temp<<1; temp=temp1; } BitCounter- -; }while(BitCounter); return(temp); }

  27. void WrToROM(unsigned int Data_Write,unsigned char Address) //Data_Write:要写的整数,Address:写入的起始地址 { unsigned char xdata Temp_Data; Start(); Send(0xa0); Ack(); Send(Address); Ack(); Temp_Data=(Data_Write>>8) & 0xff; //先写高8位 Send(Temp_Data); Ack(); Stop(); delay1ms(5); Start(); Send(0xa0); Ack(); Send(Address+1); Ack(); Temp_Data=Data_Write & 0xff; //低8位 Send(Temp_Data); Ack(); Stop(); delay1ms(5); }

  28. unsigned int RdFromROM(unsigned char Address) //读取数据 { unsigned int xdata Temp_Data; Start(); Send(0xa0); Ack(); Send(Address); Ack(); Start(); Send(0xa1); Ack(); Temp_Data=(Read())*256; //高8位 NoAck(); Stop(); delay1ms(5); Start(); Send(0xa0); Ack(); Send(Address+1); Ack(); Start(); Send(0xa1); Ack(); Temp_Data += Read(); //低8位 NoAck(); Stop(); delay1ms(5); return Temp_Data; }

  29. 通过单片机自带I2C接口 P89C669自带I2C功能实现对EEPROM单字节的读取与写入,写入单个字节和读取只要分别调用bit ISendbyte_1(uchar sla,uchar suba,uchar c)和bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no)即可,参考资料:P89C669 I2C软件包。 /******************************************************************* 申请总线 功能:进行I2C 总线的初始化包括时钟速率I2C 使能发送起始信号等 *******************************************************************/ void GetBus() { I2CON=0xc4; //use internal SCL generator I2CLL=50; //bits data rate=fosc/(I2CLL+I2CLH) I2CLH=50; I2CON=I2CON|0x20; /*STA=1,申请成为主机起动总线 */ while(SI==0); } /******************************************************************* 发送数据函数 功能:用于向总线发送数据 *******************************************************************/ void SendByte(uchar c) { I2DAT=c; I2CON=0XC4; /*清除SI 位等等 */ while(SI==0); }

  30. /********************************************** *向有子地址器件发送一个字节数据函数 ***********************************************/ bit ISendbyte_1(uchar sla,uchar suba,uchar c) { GetBus(); /*启动总线 */ SendByte(sla); /*发送器件地址 */ if(I2STAT!=0X18) { I2CON=0XD4; return(0); } SendByte(suba); /*发送器件子地址 */ if(I2STAT!=0X28) { I2CON=0XD4; return(0); } SendByte(c); /*发送数据 */ if(I2STAT!=0X28) { I2CON=0XD4; return(0); } I2CON=0XD4; /*结束总线 */ return(1); }

  31. /*******************************************************************/******************************************************************* 向有子地址器件读取多字节数据函数 函数原型: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no); 功能: 从启动总线到发送地址子地址,读数据结束总线的全过程,从器件 地址sla 子地址suba 读出的内容放入s 指向的存储区读no 个字节 如果返回1 表示操作成功否则操作有误 ********************************************************************/ bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no) { uchar i; GetBus(); /*启动总线 */ SendByte(sla); /*发送器件地址 */ if(I2STAT!=0X18) { I2CON=0XD4; return(0); } SendByte(suba); /*发送器件子地址 */ if(I2STAT!=0X28) { I2CON=0XD4; return(0); } I2CON=0XE4; /*重新启动总线 */ while(SI==0); SendByte(sla+1); if(I2STAT!=0X40) { I2CON=0XD4; return(0); }

  32. for(i=0;i<no-1;i++) { I2CON=0XC4; /*接收一字节数据并发送应答位*/ while(SI==0); if(I2STAT!=0X50) { I2CON=0XD4; return(0); } *s=I2DAT; /*读取数据 */ s++; } I2CON=0XC0; /*接收最后一字节数据并发送非应答位*/ while(SI==0); *s=I2DAT; I2CON=0XD4; /*结束总线 */ return(1); }

  33. RS232C/RS485 • 电子工业协会(EIA)公布的RS-232C是用得最多的一种串行通信标准,它是从远程通信标准中导出来的,是使用于数据终端设备(DTE)和数据通信设备(DCE)之间的接口。该标准除包括物理指标外,还包括表明按位串行传送时的电气指标。

  34. RS-232C电气特性 在电气性能方面,RS-232C使用负逻辑。逻辑“1”电平是在 -5V~-15V范围内,逻辑“0”电平是在+5V~+15V范围内。 标准要求RS-232C接收器必须能够识别+3V以上的信号作为逻辑“0”,-3V以下的信号作为逻辑“1”,即有2V的噪声容限。 RS-232C的主要电气特性见下表。

  35. RS-232C数据传送格式 RS-232C的数据传送格式是位串行方式,传输数据的格式如下图所示,这是微处理机应用系统中最通用的格式。数据的连续传送由最低有效数字位开始,以奇偶校验位作结束。 RS-485标准 : 由RS-232C的电气特性表可知,若不采用调制解调器,其传输距离很短,且最大数据传输率也受到限制。 因此,EIA又公布了能够适合于远距离传输的RS-485标准。 RS485用差分接收器接收信号电压,差分信号的抗噪声能力强。

  36. 当采用+5V电源供电时,RS-485信号定义如下: 若差分电压信号为-2500~-200mV时,为逻辑“0”; 若差分电压信号为+2500~+200mV时,为逻辑“1”;

  37. MAX485主要特征: • 采用单一电源+5 V工作,额定电流为300 μA,采用半双工通讯方式。完成将TTL电平转换为RS-485电平的功能。 • 内部含有一个驱动器和接收器。RO和DI端分别为接收器的输出和驱动器的输入端,与单片机连接时只需分别与单片机的RXD和TXD相连即可;/RE和DE端分别为接收和发送的使能端,当/RE为逻辑0时,器件处于接收状态;当DE为逻辑1时,器件处于发送状态,因为MAX485工作在半双工状态,所以只需用单片机的一个管脚控制这两个引脚即可; • A端和B端分别为接收和发送的差分信号端,当A引脚的电平高于B时,代表发送的数据为1;当A的电平低于B端时,代表发送的数据为0。 • 与单片机连接时,只需要一个信号控制MAX485的接收和发送即可。同时将A和B端之间加匹配电阻,一般可选100Ω的电阻。

  38. MAX485芯片硬件电路图

  39. void init_uart(void) //串行口初始化 { PCON = 0; // Set PCON register, clear SMOD0 and SMOD1 bits /*initiate uart0*/ T2MOD = 0; // T2OE=0;DCEN=0; S0CON = 0x50; // uart 0 in mode 1 (8 bit), REN=1 RCAP2H= 0xff; //ffb8: 9600 Bds at 11.059MHz RCAP2L= 0xb8; //ffdc: 19200 Bds at 11.059MHz TCLK=1; //T2 overflow as the baud rate generator for uart0 transmit RCLK=1; //T2 overflow as the baud rate generator for uart0 receive EXEN2=0; //ignore events on T2EX C_T2=0; //timer mode TR2=1; //timer2 run ES0R = 1 ; //开放UART0 接收中断 EA = 1; // Enable global interrupt UART1_CONTROL=R1_ENABLE;//enable UART1 receive(in max485) UART0_CONTROL=R0_ENABLE;//enable UART0 receive(in max485) } • 示例程序

  40. void respond_PLC_uart0(void) //单片机与PLC进行485通信 { uchar i=0; if((ID_num%2)==0) { ID_num_send=ID_num/2; } else if((ID_num%2)==1) { ID_num_send=(ID_num+1)/2; } ReCommand[0] = '*'; //设置起始位、从机地址、终止位 ReCommand[1] = ID_num_send; //地址 if(flag_alert_LM==1) { ReCommand[2] = 0x01; //亮度报警信息 } else { ReCommand[2] = 0x0; //正常 }

  41. ReCommand[3]=tm_send[1]; //温度值 ReCommand[4]=tm_send[0]; ReCommand[5]=lumin_buf[2]; ReCommand[6]=lumin_buf[1]; ReCommand[7]=lumin_buf[0]; ReCommand[9] = '#'; //结束位 if((MASTER==0)&&(SPARE==1)) { ReCommand[8]=0x0;//主灯工作 } else if((SPARE==0)&&(MASTER==1)) { ReCommand[8]=0x01;//备灯工作 } ES0R = 0 ; //关闭UART0 接收中断 UART0_CONTROL=T0_ENABLE; //发送使能 for(i=0;i<10;i++) { S0BUF=ReCommand[i]; while(TI_0==0) feed_watchdog(); TI_0=0; } UART0_CONTROL=R0_ENABLE;//接收使能 _nop_();_nop_();_nop_();_nop_(); ES0R = 1 ; //开放UART0 接收中断 }

  42. /******** Uart0 receive interrut****************/ void IntUart0Rx( void ) interrupt 4 { RI_0=0; //清除接收标志 if(S0BUF == '@') { Command[0]=S0BUF; UartCount =0; } else if (S0BUF == '$') { Command[3]=S0BUF; UartCount =0; } else if (UartCount < 3) { UartCount++; Command[UartCount]= S0BUF; } else UartCount =0; }

  43. SPI总线: 由同步串行外设接口SPI构成的串行总线是一种三线同步总线。总线上可以连接多个可以作为主机的微控制器MCU及装有SPI接口的I/O设备如液晶驱动、A/D转换等外设。 SPI是全双工的,即主机在发送的同时也可以在接收数据,传送的速率由主机编程决定;时钟的极性和相位也是可选择的,具体的约定由设计人员根据总线上各设备接口的功能决定。

  44. SPI具有四种工作模式,取决于时钟极性(CPOL)和时钟相位(CPHA),使用的最为广泛的是SPI0和SPI3方式。SPI具有四种工作模式,取决于时钟极性(CPOL)和时钟相位(CPHA),使用的最为广泛的是SPI0和SPI3方式。

  45. 数据在时钟信号的上升沿锁存,下降沿变化,高位在前,低位在后数据在时钟信号的上升沿锁存,下降沿变化,高位在前,低位在后

  46. //-----------------------------------------------------------------------------//----------------------------------------------------------------------------- // SPI_defs.h //----------------------------------------------------------------------------- // // This file defines the pins used for the SPI device. // The SPI device is mapped to pins P0.0 - P0.3, but can be modified to map to // any of the available GPIO pins on the device. // #ifndef SPI_DEFS #define SPI_DEFS sbit MOSI = P0^0; // Master Out / Slave In (output) sbit MISO = P0^1; // Master In / Slave Out (input) sbit SCK = P0^2; // Serial Clock (output) sbit NSS = P0^3; // Slave Select (output to chip select) #endif

  47. // SPI_Transfer mode 0 // Simultaneously transmits and receives one byte <SPI_byte> using // the SPI protocol. SCK is idle-low, and bits are latched on SCK rising. char SPI_Transfer (char SPI_byte) { unsigned char SPI_count; // counter for SPI transaction SCK = 0; for (SPI_count = 8; SPI_count > 0; SPI_count--) // single byte SPI loop { MOSI = SPI_byte & 0x80; // put current outgoing bit on MOSI SPI_byte = SPI_byte << 1; // shift next bit into MSB SCK = 0x01; // set SCK high SPI_byte |= MISO; // capture current bit on MISO SCK = 0x00; // set SCK low } return (SPI_byte); } // END SPI_Transfer

More Related