/************************************************************************** 程序名称:O22S 系列 ADC读值程序,兼容O22S-0804、O22S-3702 功能描述:本程序适合PYM2012011线路板,通信:P1.3, SDA:P1.0,SCL:P1.1 作者:刘靖 日期:2020年06月09日 ========================================================================== ----------------------修改记录-------------------------------------------- 修改人: 修改时间: 修改原因: -------------------------------------------------------------------------- 通信协议 (固定8位) 发送指令为偶数,返回为奇数 固定头 固定 指令 地址 校验 预留位 data1 data2 55 02 00 00 xx 00 00 00 //读3704 05 02 00 00 xx 00 data_L data_H //正确返回 55 02 01 00 xx 00 00 00 //读1802||0804 05 02 01 00 xx 00 data_L 00 //正确返回 55 02 02 00 xx 00 00 00 //读1806 05 02 02 00 xx 00 data_H data_L //正确返回 55 02 03 00 xx 00 00 00 //读1802||0804||3704电位器 05 02 03 00 xx 00 寄存器1 寄存器2 //正确返回 55 02 04 00 xx 00 寄存器1 寄存器2 //写1802||0804||3704电位器 05 02 04 00 xx 00 寄存器1 寄存器2 //正确返回 55 02 06 00 xx 00 00 00 //读0802电位器 05 02 06 00 xx 00 寄存器1 寄存器2 //正确返回 55 02 07 00 xx 00 寄存器1 寄存器2 //写0802电位器 05 02 07 00 xx 00 寄存器1 寄存器2 //正确返回 ========================================================================== 备注: **************************************************************************/ #include //产品需要改换型号需要改变此头文件 #include #include #define TRXD BIT3 // TXD/RXD on P1.3 //#define PWMOUT BIT2 // P1.2 #define SDA BIT0 //SDA P1.0 // #define SCL BIT1 //SLK P1.1 #define SDA1 BIT2 //SDA P1.2 //0802 IIC 通信 #define SCL1 BIT4 //SLK P2.4 #define IIC 0 #define IIC1 1 #define RECY 600 //I2C时间参数 #define DELAY_TIME 3 #define uchar unsigned char #define CPU_F ((double)12000000) #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)) ////////////////////////////////I2C通信///////////////////////////////////////// void I2C_Set_sda_high(unsigned char ucI2CNum); void I2C_Set_sda_low(unsigned char ucI2CNum); void I2C_Set_sck_high(unsigned char ucI2CNum); void I2C_Set_sck_low(unsigned char ucI2CNum); void I2C_START(unsigned char ucI2CNum); void I2C_STOP(unsigned char ucI2CNum); void I2C_TxByte(unsigned char nValue, unsigned char ucI2CNum); int I2C_RxByte(unsigned char ucFpgaNum); int I2C_GetAck(unsigned char ucFpgaNum); void I2C_SetAck(unsigned char ucI2CNum); void I2C_SetNAk(unsigned char ucI2CNum); void multi_Read_MMA8452(unsigned char SlaveAddress,unsigned char word_addr, unsigned char *pword_value, unsigned char length,unsigned char ucI2CNum); void multi_Write_MMA8452(unsigned char SlaveAddress,unsigned char word_addr, unsigned char *pword_value,unsigned char len,unsigned char ucI2CNum); unsigned char readADC_PIC16f1704(unsigned char add,unsigned char ucFpgaNum ); //void init_MCP9804(void); //void read_temp_MCP9804(void); void send(unsigned char ); void Receive(void); void init(void); void data_unbind(void); void write_Seg(unsigned char dz); //写数据 void read_SegA(unsigned char dd); void data_struct(unsigned char data0,unsigned char data1); void tmp_addr(void); unsigned int temp_data(unsigned char t_v); int fst=0; //**********************************************************************/ unsigned int mm = 0;//补偿值 unsigned int RXTXData=0; unsigned char buf_data[64];//读写64字节变量 //unsigned char RxBuf[8]={0x05,0x02,0x01,0x00,0x09,0x00,0x00,0x00};//命令字节 //unsigned char RxBuf[8]={0x05,0x02,0x03,0x00,0x0A,0x00,0x00,0x00}; unsigned char RxBuf[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //unsigned char RxBuf[8]={0};//命令字节 int UpperByte,LowerByte,Temperature,tempSign; //mcp9804回传的高字节 低字节 温度值 温度标志 unsigned int frantDot; //小数点前数据 unsigned int behindDot; //小数点后数据 unsigned char nIntValue; uchar nTemp; unsigned char BitCnt=0; unsigned char flag = 0,net_flag = 0,value = 0,t_addr = 0;//net_flag模式标识,value读单个字节存储变量,t_addr温度对应flash地址 unsigned char rxnum = 0; unsigned char step;//补偿压值变化大时,压值改变量 unsigned char Block; unsigned char high=1;//补偿压值补偿方式选择 unsigned char byteflag;//读温度标识 unsigned int tempcount=0;//计数器变量 int count=0; unsigned char BitCnt; unsigned char rxcont = 0; int Startrx_f=0; unsigned char Xor_f; unsigned char Rx_ok = 0; /***********************以下IIC通信*************************/ void I2C_Set_sda_high(unsigned char ucI2CNum) { switch(ucI2CNum) { case 0: P1REN |= SDA; P1DIR |= SDA; P1OUT |= SDA; break; case 1: P1REN |= SDA1; P1DIR |= SDA1; P1OUT |= SDA1; break; } _NOP(); _NOP(); __delay_cycles(RECY); return; } //----------------------------------------------------------------------------- //----------------------------SDA低电平的产生---------------------------------- void I2C_Set_sda_low(unsigned char ucI2CNum) { switch(ucI2CNum) { case 0: P1REN &=~ SDA; P1DIR|=SDA; P1OUT&=~(SDA); break; case 1: P1REN &=~ SDA1; P1DIR|=SDA1; P1OUT&=~(SDA1); break; } _NOP(); _NOP(); __delay_cycles(RECY); return; } //----------------------------------------------------------------------------- //-----------------------------SCL高电平的产生--------------------------------- void I2C_Set_sck_high(unsigned char ucI2CNum) { switch(ucI2CNum) { case 0: P1REN |= SCL; P1DIR |= SCL; P1OUT |= SCL; break; case 1: P2REN |= SCL1; P2DIR |= SCL1; P2OUT |= SCL1; break; } _NOP(); _NOP(); __delay_cycles(RECY); return; } //----------------------------------------------------------------------------- //------------------------------SCL低电平的产生------------------------------ void I2C_Set_sck_low(unsigned char ucI2CNum) { switch(ucI2CNum) { case 0: P1REN &=~ SCL; P1DIR|=SCL; P1OUT&=~(SCL); break; case 1: P2REN &=~ SCL1; P2DIR|=SCL1; P2OUT&=~(SCL1); break; } _NOP(); _NOP(); __delay_cycles(RECY); return; } //----------------------------------------------------------------------------- //-------------------------------启动条件------------------------------------- void I2C_START(unsigned char ucI2CNum) { I2C_Set_sda_high(ucI2CNum); I2C_Set_sck_high(ucI2CNum); I2C_Set_sda_low(ucI2CNum); I2C_Set_sck_low(ucI2CNum); return; } //----------------------------------------------------------------------------- //---------------------------停止条件------------------------------------------ void I2C_STOP(unsigned char ucI2CNum) { I2C_Set_sda_low(ucI2CNum); I2C_Set_sck_low(ucI2CNum); I2C_Set_sck_high(ucI2CNum); I2C_Set_sda_high(ucI2CNum); __delay_cycles(/*480000*/120000); //总线停止后让总线处于一定的空闲状态 return; } //----------------------------------------------------------------------------- //-----------------------数据发送---------------------------------------------- void I2C_TxByte(unsigned char nValue, unsigned char ucI2CNum) { int i; for(i=0;i<8;i++) { if(nValue & 0x80) I2C_Set_sda_high(ucI2CNum); else I2C_Set_sda_low(ucI2CNum); //delay_us(10); I2C_Set_sck_high(ucI2CNum); nValue<<=1; //delay_us(10); I2C_Set_sck_low(ucI2CNum); } return; } //----------------------------------------------------------------------------- //------------------------数据接收--------------------------------------------- int I2C_RxByte(unsigned char ucFpgaNum) { int nTemp = 0; int i; I2C_Set_sda_high(ucFpgaNum); switch(ucFpgaNum) { case 0: P1DIR &=~(SDA); P1OUT |= SDA; break; case 1: P1DIR &=~(SDA1); P1OUT |= SDA1; break; } _NOP(); _NOP(); _NOP(); _NOP(); for(i=0;i<8;i++) { I2C_Set_sck_high(ucFpgaNum); switch(ucFpgaNum) { case 0: if(P1IN&SDA) { nTemp|=(0x01<<(7-i)); } break; case 1: if(P1IN&SDA1) { nTemp|=(0x01<<(7-i)); } break; } delay_us(10); I2C_Set_sck_low(ucFpgaNum); delay_us(10); } //nIntValue = nTemp; return nTemp; } //----------------------------------------------------------------------------- //---------------------------获得ACK------------------------------------------- int I2C_GetAck(unsigned char ucFpgaNum) { int nTemp = 0; _NOP(); _NOP(); I2C_Set_sck_low(ucFpgaNum); switch(ucFpgaNum) { case 0: P1DIR &=~(SDA); break; case 1: P1DIR &=~(SDA1); break; } I2C_Set_sck_high(ucFpgaNum); switch(ucFpgaNum) { case 0: P1REN |=SDA; break; case 1: P1REN |=SDA1; break; } I2C_Set_sck_low(ucFpgaNum); switch(ucFpgaNum) { case 0: nTemp = (int)(P1IN & SDA); break; case 1: nTemp = (int)(P1IN & SDA1); break; } return (nTemp & SDA); } //----------------------------------------------------------------------------- //------------------------------ACK确认---------------------------------------- void I2C_SetAck(unsigned char ucI2CNum) { I2C_Set_sda_low(ucI2CNum); I2C_Set_sck_high(ucI2CNum); I2C_Set_sck_low(ucI2CNum); I2C_Set_sda_high(ucI2CNum); return; } //----------------------------------------------------------------------------- //--------------------------------NAK确认-------------------------------------- void I2C_SetNAk(unsigned char ucI2CNum) { I2C_Set_sck_low(ucI2CNum); I2C_Set_sda_high(ucI2CNum); I2C_Set_sck_high(ucI2CNum); I2C_Set_sck_low(ucI2CNum); return; } /***********************IIC通信*************************/ /************************O22S-3704**********************/ //读 void multi_Read_MMA8452(unsigned char SlaveAddress,unsigned char word_addr, unsigned char *pword_value, unsigned char length, unsigned char ucFpgaNum) { unsigned char i=0; I2C_START(ucFpgaNum); //起始信号 I2C_TxByte(SlaveAddress,ucFpgaNum); //发送设备地址+写信号 I2C_GetAck(ucFpgaNum); I2C_TxByte(word_addr,ucFpgaNum); //发送存储单元地址,从0x01开始 I2C_GetAck(ucFpgaNum); // delay_ms(20); delay_us(20); I2C_START(ucFpgaNum); //起始信号 I2C_TxByte(SlaveAddress+1,ucFpgaNum); //发送设备地址+读信号 I2C_GetAck(ucFpgaNum); for (i=0; i>4); //0~255 if(frantDot>128) tempSign=0; else tempSign=1; _NOP(); }*/ /////----------------------写flash------------------------//////////////// void write_Seg(unsigned char dz) { if(count<20) return; unsigned int *Flash_ptr; unsigned int *t_tab; unsigned int i; _DINT(); WDTCTL = WDTPW + WDTHOLD; for(;;) { Flash_ptr = (unsigned int *) (0x1000+dz); FCTL2 = FWKEY + FSSEL1 + FN5 + FN4; FCTL1 = FWKEY + ERASE; FCTL3 = FWKEY; *Flash_ptr = 0; FCTL1 = FWKEY; FCTL3 = FWKEY + LOCK; // lock Flash_ptr = (unsigned int *) (0x1000+dz); for (i = 0;i<32;i++) { if (*Flash_ptr != 0xFFFF) break; Flash_ptr++; } if(i != 32) continue; break; } Flash_ptr = (unsigned int *) (0x1000+dz); t_tab = (unsigned int *)buf_data; FCTL1 = FWKEY + WRT; FCTL3 = FWKEY; // Clear lock for(i=0;i<32;i++) { *Flash_ptr++ = *t_tab++; } FCTL1 = FWKEY; FCTL3 = FWKEY + LOCK; _EINT(); } void send(unsigned char mbyte ) { __delay_cycles(12000); unsigned char j; P1REN &=~ TRXD; P1IE &=~ TRXD; P1OUT |= TRXD; P1DIR |= TRXD;//输出 for(j = 0;j>=1; __delay_cycles(1230); } _NOP(); } //P1OUT |= TRXD; //init(); RxBuf[4]= (RxBuf[0] + RxBuf[1] + RxBuf[2]+ RxBuf[3] + RxBuf[5] + RxBuf[6] + RxBuf[7])&0x0F;; //RXTXData=RxBuf[0]=RxBuf[1]=RxBuf[2]=RxBuf[3]=RxBuf[4]=RxBuf[5]=RxBuf[6]=RxBuf[7]=0; //P1REN &=~ TRXD; P1OUT |= TRXD; P1REN |= TRXD; P1SEL &= ~TRXD; P1DIR &= ~TRXD; //p2.0 input P1IES |= TRXD; //download scan P1IFG = 0; P1IE |= TRXD; //enable P2.0 interrupt flag=0; } /**********************************************************************/ void Receive(void ) { // unsigned int i; P1OUT |= TRXD; P1REN |= TRXD; P1DIR &= ~TRXD; for(BitCnt=0x08;BitCnt > 0;BitCnt --) { delay_us(105); RXTXData >>=1; if(P1IN & TRXD) RXTXData |= 0x80; else RXTXData &=~ 0x80; } // RXTXData=0; } unsigned char readADC_PIC16f1704(unsigned char add,unsigned char ucFpgaNum ) { unsigned char ADC_temp=0; // int nTemp; I2C_START(ucFpgaNum); //ADDR 0X01 I2C_TxByte(0xE0,ucFpgaNum); //1010 0000 写入寄存器地址 设备地址 I2C_GetAck(ucFpgaNum); I2C_TxByte(add,ucFpgaNum); //寄存器地址 00 I2C_GetAck(ucFpgaNum); delay_us(100); I2C_START(ucFpgaNum); //ADDR 0X01 I2C_TxByte(0xE1,ucFpgaNum); //10100001 读 地址 nTemp = I2C_GetAck(ucFpgaNum); delay_us(10); ADC_temp = I2C_RxByte(ucFpgaNum); //ADC低4位 I2C_SetNAk(ucFpgaNum); I2C_STOP(ucFpgaNum); return ADC_temp; } /*************************************************************************/ void data_unbind(void) { unsigned char canversion_value[2]={0}; unsigned char set_data[2] = {0}; if(RxBuf[1]==0x02) { switch(RxBuf[2]) { case 0: //O22S-3704 multi_Read_MMA8452(0xE0,0xf0,canversion_value ,2,IIC); //RxBuf[6]=readADC_PIC16f1704(0xf0); //__delay_cycles(500000); //__delay_cycles(50000); //delay_ms(200); //RxBuf[7]=readADC_PIC16f1704(0xf1); if(canversion_value[1]>3||canversion_value[1]==0) { multi_Read_MMA8452(0xE0,0xf0,canversion_value ,2,IIC); if(canversion_value[1]>0x03||canversion_value[1]==0x00) { RxBuf[0]=0x05; RxBuf[5]=0xAA; RxBuf[6] = canversion_value[0]; RxBuf[7] = canversion_value[1]; break; } } RxBuf[6] = canversion_value[0]; RxBuf[7] = canversion_value[1]; RxBuf[0]=0x05; break; //RxBuf[4]=(RxBuf[0]+RxBuf[1]+RxBuf[2]+RxBuf[3]+RxBuf[5]+RxBuf[6]+RxBuf[7])&0x0F; // delay_ms(20); // multi_Read_MMA8452(0xE0,0xF0,canversion_value ,2); // // delay_ms(200); // RxBuf[7] = canversion_value[1]; // RxBuf[6] = canversion_value[0]; //break; case 1: //O22S-1802---O22S--0804 set_data[0] = 0x20; multi_Write_MMA8452(0xA0,0x02, set_data,1,IIC); // ADC081C027初始化 delay_ms(20); multi_Read_MMA8452(0xA0,0x00,canversion_value ,2,IIC); RxBuf[6] = ((canversion_value[0]&0x0F)<<4)|((canversion_value[1]&0xF0)>>4); if(RxBuf[6]==0||RxBuf[6]==127) { multi_Read_MMA8452(0xA0,0x00,canversion_value ,2,IIC); RxBuf[6] = ((canversion_value[0]&0x0F)<<4)|((canversion_value[1]&0xF0)>>4); if(RxBuf[6]==0x00||RxBuf[6]==0xFF) { RxBuf[0]=0x05; RxBuf[5]=0xAA; break; } } RxBuf[0]=0x05; break; case 2: //O22S-1806 set_data[0] = 0x42; set_data[1] = 0xE3; multi_Write_MMA8452(0x90,0x01, set_data,2,IIC); // SGM初始化 delay_ms(20); multi_Read_MMA8452(0x90,0x00,canversion_value ,2,IIC); if(canversion_value[1]==0x00||canversion_value[1]==0xFF) { multi_Read_MMA8452(0x90,0x00,canversion_value ,2,IIC); if(canversion_value[1]==0x00||canversion_value[1]==0xFF) { RxBuf[0]=0x05; RxBuf[5]=0xAA; RxBuf[7] = canversion_value[0]; RxBuf[6] = canversion_value[1]; break; } } RxBuf[7] = canversion_value[0]; RxBuf[6] = canversion_value[1]; RxBuf[0]=0x05; break; case 3: //读拐点 multi_Read_MMA8452(0x5C,0x2C,canversion_value ,2,IIC); RxBuf[6] = canversion_value[1]; canversion_value[0]=canversion_value[1]=0; delay_ms(20); multi_Read_MMA8452(0x5C,0x3C,canversion_value ,2,IIC); RxBuf[7] = canversion_value[1]; P1OUT |= SCL; P1REN &=~ SCL; P1SEL &= ~SCL; P1DIR &=~ SCL; RxBuf[0]=0x05; break; case 4: //写拐点 set_data[0] = RxBuf[6]; multi_Write_MMA8452(0x5C,0x00, set_data,1,IIC); // delay_ms(20); multi_Write_MMA8452(0x5C,0x20, set_data,1,IIC); set_data[0] = RxBuf[7]; multi_Write_MMA8452(0x5C,0x10, set_data,1,IIC); // delay_ms(20); multi_Write_MMA8452(0x5C,0x30, set_data,1,IIC); P1OUT |= SCL; P1REN &=~ SCL; P1SEL &=~ SCL; P1DIR &=~ SCL; RxBuf[0]=0x05; break; case 5: //1806读拐点 multi_Read_MMA8452(0x5C,0x2C,canversion_value ,2,IIC); RxBuf[6] = canversion_value[1]; canversion_value[0]=canversion_value[1]=0; delay_ms(20); multi_Read_MMA8452(0x5C,0x3C,canversion_value ,2,IIC); RxBuf[7] = canversion_value[1]; RxBuf[0]=0x05; break; case 6: //0802读拐点 multi_Read_MMA8452(0x5C,0x2C,canversion_value ,2,IIC1); RxBuf[6] = canversion_value[1]; canversion_value[0]=canversion_value[1]=0; delay_ms(20); multi_Read_MMA8452(0x5C,0x3C,canversion_value ,2,IIC1); RxBuf[7] = canversion_value[1]; P1OUT |= SCL; P1REN &=~ SCL; P1SEL &= ~SCL; P1DIR &=~ SCL; RxBuf[0]=0x05; break; case 7: //0802写拐点 set_data[0] = RxBuf[6]; multi_Write_MMA8452(0x5C,0x00, set_data,1,IIC1); // delay_ms(20); multi_Write_MMA8452(0x5C,0x20, set_data,1,IIC1); set_data[0] = RxBuf[7]; multi_Write_MMA8452(0x5C,0x10, set_data,1,IIC1); // delay_ms(20); multi_Write_MMA8452(0x5C,0x30, set_data,1,IIC1); P1OUT |= SCL; P1REN &=~ SCL; P1SEL &=~ SCL; P1DIR &=~ SCL; RxBuf[0]=0x05; break; } } // RxBuf[5]=0x01; send(8); //RxBuf[0]=0; } /**********************************************************/ void init(void) { WDTCTL = WDTPW + WDTHOLD; //WDTCTL = WDT_MRST_32; BCSCTL1= CALBC1_1MHZ; //1Mhz DCOCTL = CALDCO_1MHZ; //延迟50ms,等待系统稳定 P1SEL &=~SCL; //初始化IO口 P1SEL &=~SDA; //初始化IO口 // P1OUT |= SCL; P1REN |= SCL; //P1.0上拉电阻打开 P1REN |= SDA; //P1.1上拉电阻打开 // P1DIR &= ~SCL; P2SEL &=~SCL1; //初始化IO口 P1SEL &=~SDA1; //初始化IO口 // P2OUT |= SCL1; P2REN |= SCL1; //P2.4上拉电阻打开 P1REN |= SDA1; //P1.2上拉电阻打开 // P2DIR &= ~SCL1; /***********************************************************************/ // CCR1 = (PWM_CCR0>>1);////CCR1 = (PWM_CCR0>>1); // //CCR1 = PWM_CCR0 - 10;////CCR1 = PWM_CCR0 - 10; // CCR0 = PWM_CCR0; // CCTL0 = 0; // //CCTL1 = OUTMOD2 + OUTMOD1 + OUTMOD0 + OUT ; // CCR1 reset/set // CCTL1 = OUTMOD_7; // CCTL2 = CCIE; // TACTL = TASSEL_2 + MC_1; //start timera up to ccr0 mode + TACLR // P1SEL |= PWMOUT; // P1.2 // P1DIR |= PWMOUT; // P1.2 /*******************************PWM***********************************/ P1OUT |= TRXD; P1REN |= TRXD; P1SEL &= ~TRXD; P1DIR &= ~TRXD; //p2.0 input P1IES |= TRXD; //download scan P1IFG = 0; P1IE |= TRXD; //enable P2.0 interrupt flag=0; byteflag = 0; WDTCTL = WDTPW + WDTHOLD; } /*****************************************************************************/ //----------------------------------------------------------------------------- void main(void) { WDTCTL = WDTPW + WDTHOLD; __delay_cycles(500000); init(); __delay_cycles(500000); BCSCTL1= CALBC1_12MHZ; //12Mhz DCOCTL = CALDCO_12MHZ; __delay_cycles(500000); _EINT(); for(;;) { if(Rx_ok == 1) { Rx_ok = 0; data_unbind(); } delay_ms(20); // send(0x55); // send(1); } } /***************************************************************************/ #pragma vector = PORT1_VECTOR __interrupt void ISR_P13(void) { uchar j=0; if( P1IFG ) { delay_us(20); //9600bps P1IE &= ~TRXD; Receive(); // RxBuf[0]=RXTXData; //send(1); if(Startrx_f == 0) { if(RXTXData == 0x55) { Startrx_f = 1; RxBuf[0]=RXTXData; RXTXData = 0; } } else { rxcont++; RxBuf[rxcont] = RXTXData; RXTXData = 0; if(rxcont >6) { rxcont = 0; Startrx_f = 0; //判断校验和和命令格式 Xor_f=0; for(j=0;j<8;j++) { if(j != 4) { Xor_f=(Xor_f+RxBuf[j])&0x0f; } } if(Xor_f == RxBuf[4]) //校验成功 { Rx_ok=1; //接收命令成功标志 } } } } //Receive(8); P1IFG = 0; P1IE |= TRXD; //enable P2.0 interrupt }