51单片机搭建气敏测试系统
本项目使用51芯片为核心,控制一颗模数转换器PCF8591和一颗数模转换器tlc5615控制流量计控制器,并通过串口向上位机发送当前流量值
目录
1 模拟iic对芯片的控制
2 spi数模转换
由pcf8591数据手册信号建立时间与保持时间得模拟时序
1 void Start_I2c() 2 { 3 sda=1; 4 _nop_(); 5 scl=1; 6 _nop_(); 7 _nop_(); 8 _nop_(); 9 _nop_(); 10 _nop_(); 11 sda=0; 12 _nop_(); 13 _nop_(); 14 _nop_(); 15 _nop_(); 16 _nop_(); 17 scl=0; 18 _nop_(); 19 _nop_(); 20 }
1 void Stop_I2c() 2 { 3 sda=0; 4 _nop_(); 5 scl=1; 6 _nop_(); 7 _nop_(); 8 _nop_(); 9 _nop_(); 10 _nop_(); 11 sda=1; 12 _nop_(); 13 _nop_(); 14 _nop_(); 15 _nop_(); 16 }
发送字节函数
1 void I2C_SendByte(unsigned char c) 2 { 3 unsigned char i; 4 5 for(i=0;i<8;i++) 6 { 7 if((c<<i)&0x80)sda=1; 8 else sda=0; 9 _nop_(); 10 scl=1; 11 _nop_(); 12 _nop_(); 13 _nop_(); 14 _nop_(); 15 _nop_(); 16 scl=0; 17 } 18 19 _nop_(); 20 _nop_(); 21 sda=1; 22 _nop_(); 23 scl=1; 24 _nop_(); 25 _nop_(); 26 _nop_(); 27 if(sda==1)ack=0; 28 else ack=1; 29 scl=0; 30 _nop_(); 31 _nop_(); 32 }
1 unsigned char I2C_RcvByte() 2 { 3 unsigned char retc=0,i; 4 sda=1; 5 for(i=0;i<8;i++) 6 { 7 _nop_(); 8 scl=0; 9 _nop_(); 10 _nop_(); 11 _nop_(); 12 _nop_(); 13 scl=1; 14 _nop_(); 15 _nop_(); 16 retc=retc<<1; 17 if(sda==1)retc=retc+1; 18 _nop_(); 19 _nop_(); 20 } 21 scl=0; 22 _nop_(); 23 _nop_(); 24 return(retc); 25 }
1 void Ack_I2c(bit a) 2 { 3 if(a==0)sda=0; 4 else sda=1; 5 _nop_(); 6 _nop_(); 7 _nop_(); 8 scl=1; 9 _nop_(); 10 _nop_(); 11 _nop_(); 12 _nop_(); 13 _nop_(); 14 scl=0; 15 _nop_(); 16 _nop_(); 17 }
主要函数调用:
此芯片地址一个字节控制一个字节,因此发送两个字节进行配置
1 bit PCF8591_SendByte(unsigned char addr,unsigned char channel) 2 { 3 Start_I2c(); 4 I2C_SendByte(addr); //发送器件地址 5 if(ack==0)return(0); 6 I2C_SendByte(0x40|channel); 7 if(ack==0)return(0); 8 Stop_I2c(); 9 return(1); 10 }
配置成功即受到应答则直接结束返回0
没有找到从芯片则返回0
1 unsigned char PCF8591_RcvByte(unsigned char addr) 2 { 3 unsigned char dat; 4 5 Start_I2c(); 6 I2C_SendByte(addr+1); 7 if(ack==0)return(0); 8 dat=I2C_RcvByte(); 9 10 Ack_I2c(1); 11 Stop_I2c(); 12 return(dat); 13 }
数模转换部分(tlc5615使用三线spi,只有片选,时钟,MOSI线,只能半双工):
1 void DA5615(u16 j) 2 { 3 4 u16 i; 5 6 u8 temp; 7 temp=j; 8 CLK=0; 9 CS=0; 10 for(i=0;i<12;i++) 11 12 { 13 temp=temp<<1; 14 15 DIN=CY; 16 17 CLK=1; 18 19 _nop_(); 20 21 CLK=0; 22 23 } 24 25 CS=1; 26 }
1 void UsartInit() 2 { 3 SCON=0X50; 4 TMOD=0X20; 5 6 TH1 = 0xFD; 7 TL1 = TH1; 8 PCON = 0x00; 9 ES=1; 10 EA=1; 11 TR1=1; 12 } 13 void send_str(u8 *p) 14 { 15 16 while(*p) 17 { 18 SBUF=*p; 19 20 p++; 21 while(!TI); 22 TI=0;} 23 24 } 25 void Usart() interrupt 4 26 { 27 28 u8 receiveData,i; 29 30 receiveData=SBUF; 31 RI = 0; 32 33 data[i] = receiveData; 34 i++; 35 if (receiveData == '\n') 36 37 { 38 flag=1; 39 40 } 41 42 }
接收到的上位机命令为询问命令时,将ADC转换结果发送至上位机端:
1 union Udata{ 2 3 unsigned char ch[2]; 4 u16 ad; 5 6 }; 7 union Udata ad_value; 8 if(strcmp(data,"read?\n")==0 ) 9 { PCF8591_SendByte(AddWr,3); 10 ADtemp = PCF8591_RcvByte(AddWr); 11 ad_value.ad = ADtemp; 12 send_str(ad_value.ch); 13 14 }