//******************************************** unsigned int SD_CMD_Write(unsigned int CMDIndex,unsigned long CMDArg,unsigned int ResType,unsigned int CSLowRSV)//ResType:Response Type, send 1 for R1; send 2 for R1b; send 3 for R2. { //There are 7 steps need to do.(marked by [1]-[7]) unsigned int temp,Response,Response2,CRC,MaximumTimes; Response2=0; MaximumTimes=10; CRC=0x0095;//0x0095 is only valid for CMD0 if (CMDIndex!=0) CRC=0x00ff; sd_cse=0;//[1] CS Low SD_2Byte_Write(((CMDIndex|0x0040)<<8)+(CMDArg>>24));//[2] Transmit Command_Index & 1st Byte of Command_Argument. SD_2Byte_Write((CMDArg&0x00ffff00)>>8); //[2] 2nd & 3rd Byte of Command_Argument SD_2Byte_Write(((CMDArg&0x000000ff)<<8)+CRC); //[2] 4th Byte of Command_Argument & CRC only for CMD0 sd_dao=1;//[3] Do High //[3] Restore Do to High Level for (temp=0;temp<8;temp++)//[4] Provide 8 extra clock after CMD { sd_clk=0;//CLK Low Delay5us(); sd_clk=1;//CLK High Delay5us(); } switch (ResType)//[5] wait response { case 1://R1 { do Response=SD_Read(); while (Response==0xffff); break; } case 2://R1b { do Response=SD_Read(); while (Response==0xffff);//Read R1 firstly do Response2=SD_Read()-0xff00; while (Response2!=0);//Wait until the Busy_Signal_Token is non-zero break; } case 3: Response=SD_2Byte_Read();break;//R2 } if (CSLowRSV==0) sd_cse=1;//[6] CS High (if the CMD has data block response CS should be kept low) for (temp=0;temp<8;temp++)//[7] Provide 8 extra clock after card response { sd_clk=0;//CLK Low Delay5us(); sd_clk=1;//CLK High Delay5us(); } return Response; }
void I2C_Stop(void) { SDA_L; Delay5us(); SCL_H; SDA_H; Delay5us(); }
void I2C_nack(void) { SDA_H; SCL_H; Delay5us(); SCL_L; Delay5us(); }
//************************************************************************************************* //I2C停止信号 //************************************************************************************************* void I2C_Stop() { SDA = 0; //拉低数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时 SDA = 1; //产生上升沿 Delay5us(); //延时 }
void I2C_SendACK(bit ack) { SDA = ack; SCL = 1; Delay5us(); SCL = 0; Delay5us(); }
void I2C_Start(void) { SDA_H; SCL_H; Delay5us(); SDA_L; SCL_L; Delay5us(); }
//************************************************************************************************** //I2C发送应答信号 //入口参数:ack (0:ACK 1:NAK) //************************************************************************************************** void I2C_SendACK(bit ack) { SDA = ack; //写应答信号 SCL = 1; //拉高时钟线 Delay5us(); //延时 SCL = 0; //拉低时钟线 Delay5us(); //延时 }
void I2C_Stop() { SDA = 0; SCL = 1; Delay5us(); SDA = 1; Delay5us(); }
//**************************************************************************************************** //I2C接收应答信号 //**************************************************************************************************** bit I2C_RecvACK() { SCL = 1; //拉高时钟线 Delay5us(); //延时 CY = SDA; //读应答信号 SCL = 0; //拉低时钟线 Delay5us(); //延时 return CY; }
void I2C_Start() { SDA = 1; SCL = 1; Delay5us(); SDA = 0; Delay5us(); SCL = 0; }
bit I2C_RecvACK() { SCL = 1; Delay5us(); CY = SDA; SCL = 0; Delay5us(); return CY; }
//************************************************************************************************* //I2C起始信号 //************************************************************************************************* void I2C_Start() { SDA = 1; //拉高数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时 SDA = 0; //产生下降沿 Delay5us(); //延时 SCL = 0; //拉低时钟线 }
u8 I2C_Slave_ACK(void) { //0ACK u8 s, ack; SCL_H; Delay5us(); s = SDA_read; if(s) ack = 1; else ack = 0; SCL_L; Delay5us(); return ack; }
//***************************************************************************************************** //向I2C总线发送一个字节数据 //***************************************************************************************************** void I2C_SendByte(uchar dat) { uchar i; for (i=0; i<8; i++) //8位计数器 { dat <<= 1; //移出数据的最高位 SDA = CY; //送数据口 SCL = 1; //拉高时钟线 Delay5us(); //延时 SCL = 0; //拉低时钟线 Delay5us(); //延时 } I2C_RecvACK(); }
void I2C_SendByte(unsigned char dat) { unsigned char i; for(i=0; i<8; i++) { dat <<= 1; SDA = CY; SCL = 1; Delay5us(); SCL = 0; Delay5us(); } I2C_RecvACK(); }
u8 I2C_RecvByte(void) { u8 i; u8 ReceiveByte = 0; for(i = 0; i < 8; i++) { ReceiveByte <<= 1; SCL_H; Delay5us(); if(SDA_read) { ReceiveByte |= 0x01; } SCL_L; Delay5us(); } return ReceiveByte; }
//******************************************** unsigned int SD_Reset_Card() { unsigned int temp,MaximumTimes; MaximumTimes=10; for (temp=0;temp<80;temp++)//Send 74+ Clocks { sd_clk=0;//CLK Low Delay5us(); sd_clk=1;//CLK High Delay5us(); } return SD_CMD_Write(0x0000,0x00000000,1,0);//Send CMD0 }
//***************************************************************************************************** //从I2C总线接收一个字节数据 //****************************************************************************************************** uchar I2C_RecvByte() { uchar i; uchar dat = 0; SDA = 1; //使能内部上拉,准备读取数据, for (i=0; i<8; i++) //8位计数器 { dat <<= 1; SCL = 1; //拉高时钟线 Delay5us(); //延时 dat |= SDA; //读数据 SCL = 0; //拉低时钟线 Delay5us(); //延时 } return dat; }
void I2C_SendByte(u8 SendByte) { u8 i; for(i = 0; i < 8; i++) { Delay5us(); if(SendByte & 0x80) SDA_H; else SDA_L; SendByte <<= 1; Delay5us(); SCL_H; Delay5us(); SCL_L; Delay5us(); } }
unsigned char I2C_RecvByte() { unsigned char i; unsigned char dat = 0; SDA = 1; for(i=0; i<8; i++) { dat <<= 1; SCL = 1; Delay5us(); dat |= SDA; SCL = 0; Delay5us(); } return dat; }
void LCD1602_WriteCom(uint8_t command) { LCD1602_RS_L; LCD1602_RW_L; LCD1602_SetPortData(command>>4);//閸ユ稓鍤庡Ο鈥崇础閸忓牆鍟撴妯虹摟閼猴拷 Delay5us(); LCD1602_EN_H; Delay5us(); LCD1602_EN_L; LCD1602_SetPortData(command&0x0F);//閸愬秴鍟撴担搴℃磽娴e秴鐡ч懞锟� Delay5us(); LCD1602_EN_H; Delay5us(); LCD1602_EN_L; Delay5us(); }
void LCD1602_WriteDat(uint8_t dat) { LCD1602_RS_H; LCD1602_RW_L; LCD1602_SetPortData(dat>>4);//閸ユ稓鍤庡Ο鈥崇础閸忓牆鍟撴妯虹摟閼猴拷 Delay5us(); LCD1602_EN_H; Delay5us(); LCD1602_EN_L; LCD1602_SetPortData(dat&0x0F);//閸愬秴鍟撴担搴℃磽娴e秴鐡ч懞锟� Delay5us(); LCD1602_EN_H; Delay5us(); LCD1602_EN_L; Delay5us(); }
//WriteSPI_to_LCD() Function: //WriteSPI_to_LCD() writes 32 characters to the 2x16 LCD //using the SPI1 interface in a polling fashion. //After each byte is written, the Interrupt Flag bit is polled and the //next character is written after the interrupt flag bit is set. void WriteSPI_to_LCD(void) { int temp, i; i=0; temp = SPI1BUF; SPI1STATbits.SPIROV = 0; IFS0bits.SPI1IF = 0; Delay5us(50); SPI1BUF = LCDLINE1CMD; //First write the command to set cursor //to Line1 on LCD LCDCharPtr = &DisplayData[0]; //Set up LCD character pointer to point //to the Display buffer while(i < 16) { while (IFS0bits.SPI1IF=0); //Now write 16 characters temp = SPI1BUF; //to Line 1 of the LCD IFS0bits.SPI1IF = 0; SPI1STATbits.SPIROV = 0; Delay5ms(1); SPI1BUF = *LCDCharPtr++; i++; } while (IFS0bits.SPI1IF==0); temp = SPI1BUF; IFS0bits.SPI1IF = 0; SPI1STATbits.SPIROV = 0; temp = *LCDCharPtr++; //Some characters in the Display buffer temp = *LCDCharPtr++; //are skipped while writing to LCD. CR Delay5us(50); //and LF are for writing to RS2322 UART SPI1BUF = LCDLINE2CMD; //Next, write the command to set cursor //to Line2 on LCD i = 0; while(i < 16) { while (IFS0bits.SPI1IF==0); //Now write 16 characters temp = SPI1BUF; //to Line 2 of the LCD IFS0bits.SPI1IF = 0; SPI1STATbits.SPIROV = 0; Delay5us(50); SPI1BUF = *LCDCharPtr++; i++; } }
//******************************************** unsigned int Write_Single_Block(unsigned long int BlockAddress) { unsigned int temp,Response,MaximumTimes; MaximumTimes=10; if (BlockAddress>BlockNR) return 0xff20;//whether BlockAddress out of range? for(temp=0;temp<MaximumTimes;temp++) { Response=SD_CMD_Write(24,BlockAddress,1,1);//Send CMD24 if (Response==0xff00) temp=MaximumTimes; } for (temp=0;temp<8;temp++)//Provide 8 extra clock after CMD response { sd_clk=0;//CLK Low Delay5us(); sd_clk=1;//CLK High Delay5us(); } SD_Write(0x00fe);//Send Start Block Token //这里为了使只有512byte的单片机能够读写SD卡,特意节省了RAM的使用量,每次读写只有两个重复的128byte //如果您使用的单片机拥有1K以上的RAM请将"%128"去掉 for (temp=0;temp<256;temp++) SD_2Byte_Write(WriteBuffer[temp%128]);//Data Block SD_2Byte_Write(0xffff);//Send 2 Bytes CRC Response=SD_Read(); while (SD_Read()!=0xffff) {;} sd_cse=1;//CS_High() for (temp=0;temp<8;temp++)//Provide 8 extra clock after data response { sd_clk=0;//CLK Low Delay5us(); sd_clk=1;//CLK High Delay5us(); } return Response; }
//******************************************** unsigned int Read_Single_Block(unsigned long int BlockAddress) { unsigned int temp,Response,MaximumTimes; MaximumTimes=10; if (BlockAddress>BlockNR) return 0xff20;//whether BlockAddress out of range? for(temp=0;temp<MaximumTimes;temp++) { Response=SD_CMD_Write(17,BlockAddress,1,1);//Send CMD17 if (Response==0xff00) temp=MaximumTimes; } while (SD_Read()!=0xfffe) {;} //这里为了使只有512byte的单片机能够读写SD卡,特意节省了RAM的使用量,每次读写只有两个重复的128byte //如果您使用的单片机拥有1K以上的RAM请将"%128"去掉 for (temp=0;temp<256;temp++) ReadBuffer[temp%128]=SD_2Byte_Read();//Get the readed data for (temp=0;temp<16;temp++)//Provide 16 clock to remove the last 2 bytes of data response (CRC) { sd_clk=0;//CLK Low Delay5us(); sd_clk=1;//CLK High Delay5us(); } sd_cse=1;//CS_High() for (temp=0;temp<8;temp++)//Provide 8 extra clock after data response { sd_clk=0;//CLK Low Delay5us(); sd_clk=1;//CLK High Delay5us(); } return Response; }
//******************************************** unsigned int SD_Read() { unsigned int Buffer; unsigned char BitCounter; Buffer=0xffff; for (BitCounter=0;BitCounter<8;BitCounter++) { sd_clk=0;//CLK Low Delay5us(); sd_clk=1;//CLK High Buffer=Buffer<<1;//Because the MSB is transmitted firstly, shift to next lower bit. //Because the LSB will be damaged, we can not put this line under next line. if(sd_dai) Buffer++;//If SPI_Din=1 then the LSB_of_Buffer=1. } return Buffer; }
//******************************************** void SD_2Byte_Write(unsigned int IOData) { unsigned char BitCounter; for (BitCounter=0;BitCounter<16;BitCounter++) { sd_clk=0;//CLK Low if(IOData&0x8000)//If the MSB of IOData is 1, then Do=1, else Do=0. sd_dao=1;//Do High else sd_dao=0;//Do Low sd_clk=1;//CLK High Delay5us(); IOData=IOData<<1;//Because the MSB is transmitted firstly, shift to next lower bit. } }
//******************************************** unsigned int SD_Get_CardInfo()//Read CSD register { unsigned int temp,Response,MaximumTimes; MaximumTimes=50; for(temp=0;temp<MaximumTimes;temp++) { Response=SD_CMD_Write(9,0x00000000,1,1);//Send CMD9 if (Response==0xff00) temp=MaximumTimes; } for (temp=0;temp<8;temp++)//Provide 8 clock to romove the first byte of data response (0x00fe) { sd_clk=0;//CLK Low Delay5us(); sd_clk=1;//CLK High Delay5us(); } for (temp=0;temp<8;temp++) ReadBuffer[temp]=SD_2Byte_Read();//Get the CSD data for (temp=0;temp<16;temp++)//Provide 16 clock to remove the last 2 bytes of data response (CRC) { sd_clk=0;//CLK Low Delay5us(); sd_clk=1;//CLK High Delay5us(); } sd_cse=1;//CS_High() for (temp=0;temp<8;temp++)//Provide 8 extra clock after data response { sd_clk=0;//CLK Low Delay5us(); sd_clk=1;//CLK High Delay5us(); } BlockNR=((ReadBuffer[3]<<2)&0x0fff)+((ReadBuffer[4]>>14)&0x0003)+1;//Calcuate MULT BlockNR=BlockNR*(0x0002<<(((ReadBuffer[4]<<1)&0x0007)+((ReadBuffer[5]>>15)&0x0001)+1));//Calcuate Block_Number return Response; }
//******************************************** unsigned int SD_Get_CardID()//Read CID register { unsigned int temp,Response,MaximumTimes; MaximumTimes=10; for(temp=0;temp<MaximumTimes;temp++) { Response=SD_CMD_Write(10,0x00000000,1,1);//Send CMD9 if (Response==0xff00) temp=MaximumTimes; } for (temp=0;temp<8;temp++)//Provide 8 clock to romove the first byte of data response (0x00fe) { sd_clk=0;//CLK Low Delay5us(); sd_clk=1;//CLK High Delay5us(); } for (temp=0;temp<8;temp++) ReadBuffer[temp]=SD_2Byte_Read();//Get the CID data for (temp=0;temp<16;temp++)//Provide 16 clock to remove the last 2 bytes of data response (CRC) { sd_clk=0;//CLK Low Delay5us(); sd_clk=1;//CLK High Delay5us(); } sd_cse=1;//CS_High() for (temp=0;temp<8;temp++)//Provide 8 extra clock after data response { sd_clk=0;//CLK Low Delay5us(); sd_clk=1;//CLK High Delay5us(); } return Response; }