My senior sister (PhD) reverse-designed the ADS7841 chip. In order to test its stability and accuracy, she helped write this driver. My senior brother originally wrote it with FPGA, but the data read out was too different, so I used a 430 microcontroller to help me make one! But the debugging of this program was not smooth, it was just painful. I didn't eat lunch and dinner yesterday! First, I encountered a broken I/O port, and the description of the reading in the DATASHEET of this chip was wrong, which was very harmful! According to the datasheet, it is necessary to wait for the busy signal to be low before starting to read. In fact, it is too late at this time and one bit will be missed. All the above problems were found out with the help of a logic analyzer. I analyzed the captured timing bit by bit and finally found the loophole of the DATASHEET in the reading. In addition, she did not mention which edge of the clock should be used to trigger writing and reading data respectively. It is really depressing~! Normally, the instruction should be written on the falling edge and the data should be read on the rising edge!
It took a day to get the result. If it weren't for the help of the logic analyzer, I guess I would not know how I died. .
Okay, the situation is explained, and the following is the code part.
*********************************************************************************
** Function prototype: unsigned int ADS7841_Read_Data(unsigned char Channel);
** Function: A/D ADS7841 driver program of SPI bus
** Input parameter: unsigned char Channel indicates the selection of reading channel
** Output parameter: unsigned int returns the 12-bit data read.
** Description: ADS7841 is a 12-bit A/D. Set it first: data bits D0---D7, where D0---D1 is
** Set the ADC power consumption mode, D2 is the analog input channel setting, H is 4 single channels, L is two
** differential inputs, D3 is mode, when mode (pin) is grounded, it is a 12-bit sampling mode, when connected to a high level
** mode is 1 when 8-bit acquisition, 0 when 12-bit acquisition, D4---D6 for input channel selection, D7 is the start bit
** Author: Thinking Fish
** Date: November 6, 2007
**-----------------------------------------------------------------------------
** Modifier:
** Date:
***************************************************************************/
#include
#define uint unsigned int
#define uchar unsigned char
#define ADS_S 0x80 //Command start bit
#define ADS_MODE 0x08 //Mode selection. MODE terminal selection directly connected to high level, this bit does not need to be set
#define ADS_S_D 0x04 //Input mode selection
#define ADS_POWER 0x00 //Whether to allow power off
#define DIR_CS P3DIR|=BIT0
#define ADS_CS_1 P3OUT|=BIT0
#define ADS_CS_0 P3OUT&=~BIT0 //Chip select
#define ADS_DIR_IN P3DIR|=BIT1 //Port output mode
#define ADS_DIN_1 P3OUT|=BIT1 //Command write AD
#define ADS_DIN_0 P3OUT&=~BIT1
#define ADS_DIR_OT P2DIR&=~BIT0 //Port is in input mode
#define ADS_CLK_DIR P4DIR|=BIT4 //Port is in output mode
#define ADS_CLK_1 P4OUT|=BIT4 //Clock is set to 1
#define ADS_CLK_0 P4OUT&=~BIT4 //Set clock to 0
#define DIR_BUSY P4DIR&=~BIT0
//#define DATA_IN ((P4IN>>2 & 0x01)
#define DATA_IN (P2IN & 0x01)
#define BUSY_IN (P4IN & 0x01) //Read input data
void Check_busy(void);
void SPI_WR(uchar DATA) ;
void Init_Port(void);
void delay(uint temp);
uint ADS7841_Read_Data(uchar Channel);
uint temp_DATA[100];
void delay(uint temp1)
{
int i;
for(i=temp1;i>0;i--)
{
;
}
}
uint ADS7841_Read_Data(uchar Channel) //Channel=0:CH0;1:CH1;2:CH2;3: CH3;
{
uint ADCResult=0;
uchar i,ADS_CHANNEL;
uint TempBit =0;
uchar COMMAND=0;
switch (Channel)
{
case 0:ADS_CHANNEL=0x10;break; //Channel selection
case 1:ADS_CHANNEL=0x50;break;
case 2:ADS_CHANNEL=0x20;break;
case 3:ADS_CHANNEL=0x60;break;
default:ADS_CHANNEL=0x10;break;
}
COMMAND=(ADS_S|ADS_CHANNEL|ADS_S_D|ADS_POWER);
ADS_CLK_0;
ADS_DIN_0; ///DIN is set to 0 first
ADS_CS_0; //;Chip select signal
//SPI_WR(COMMAND); //SPI bus write command subroutine
//ADS_DIR_IN; //Port is defined as output mode, rising edge sends, falling edge receives
for(i=0;i<8;i++)
{
ADS_CLK_1;
if( (COMMAND & 0x80) ==0x80)
{
ADS_DIN_1; //Write instruction
}
else
{
ADS_DIN_0;
}
COMMAND<<=1; //Left shift
delay(5);
ADS_CLK_0;
delay(5); //Simulate SPI serial interface to send data
}
delay(5);
ADS_CLK_0;
Check_busy();
//delay(5);
for(i=0;i<12;i++)
{ //Rising edge read data
ADS_CLK_0;
delay(4);
if( DATA_IN==0x01 )
{
TempBit=1;
}
else
{
TempBit=0;
}
ADS_CLK_1;
ADCResult=((ADCResult<<1)|TempBit); //Simulate SPI serial interface, receive data
delay(5);
}
ADS_CLK_0;
for(i=0;i<4;i++)
{
ADS_CLK_1;
delay(5);
ADS_CLK_0;
delay(5);
}
ADS_CS_1; //Shield chip select
return ADCResult;
}
void Check_busy(void)
{
int temp;
//DIR_BUSY; //Port is set to input mode
ADS_CLK_1;
temp=BUSY_IN;
ADS_CLK_0;
while( (temp&0x01)==0) //Start reading when high level is detected. . Otherwise, one bit will be lost
{
ADS_CLK_1; //Read port status....
temp=BUSY_IN;
//delay(5); //
ADS_CLK_0;
}
//
/* do
{
ADS_CLK_0; //Read port status....
temp=BUSY_IN;
delay(5); //
ADS_CLK_1;
}while((temp&0x01)!=0); //High bit is 1 for busy signal*/
}
void SPI_WR(uchar DATA)
{
uint i;
ADS_DIR_IN; //Port is defined as output mode, rising edge sends, falling edge receives
for(i=0;i<8;i++)
{
ADS_CLK_1;
if( (DATA & 0x80) ==0x80)
{
ADS_DIN_1; //write instruction
}
else
{
ADS_DIN_0;
}
DATA<<=1; //left shift
ADS_CLK_0;
delay(5); //simulate SPI serial interface to send data
}
delay(5);
ADS_CLK_0;
}
void Init_Port(void)
{
P3SEL=0X00;
P4SEL=0X00;
ADS_DIR_IN;
ADS_DIR_OT;
ADS_CLK_DIR;
DIR_BUSY;
DIR_CS;
ADS_CLK_0;
//delay(5);
ADS_CS_1;
// ADS_CLK_1;
}
void main(void)
{
WDTCTL = WDTPW+WDTHOLD; //turn off watchdog
Init_Port(); //port initialization
uint flag=0;
uint i;
while(1)
{
for(i=0;i<5;i++)
{
temp_DATA[i]=ADS7841_Read_Data(0);
delay(10);
}
flag=1;
}
}
Keywords:MSP430 ADS7841 Driver
Reference address:ADS7841 driver based on MSP430
It took a day to get the result. If it weren't for the help of the logic analyzer, I guess I would not know how I died. .
Okay, the situation is explained, and the following is the code part.
*********************************************************************************
** Function prototype: unsigned int ADS7841_Read_Data(unsigned char Channel);
** Function: A/D ADS7841 driver program of SPI bus
** Input parameter: unsigned char Channel indicates the selection of reading channel
** Output parameter: unsigned int returns the 12-bit data read.
** Description: ADS7841 is a 12-bit A/D. Set it first: data bits D0---D7, where D0---D1 is
** Set the ADC power consumption mode, D2 is the analog input channel setting, H is 4 single channels, L is two
** differential inputs, D3 is mode, when mode (pin) is grounded, it is a 12-bit sampling mode, when connected to a high level
** mode is 1 when 8-bit acquisition, 0 when 12-bit acquisition, D4---D6 for input channel selection, D7 is the start bit
** Author: Thinking Fish
** Date: November 6, 2007
**-----------------------------------------------------------------------------
** Modifier:
** Date:
***************************************************************************/
#include
#define uint unsigned int
#define uchar unsigned char
#define ADS_S 0x80 //Command start bit
#define ADS_MODE 0x08 //Mode selection. MODE terminal selection directly connected to high level, this bit does not need to be set
#define ADS_S_D 0x04 //Input mode selection
#define ADS_POWER 0x00 //Whether to allow power off
#define DIR_CS P3DIR|=BIT0
#define ADS_CS_1 P3OUT|=BIT0
#define ADS_CS_0 P3OUT&=~BIT0 //Chip select
#define ADS_DIR_IN P3DIR|=BIT1 //Port output mode
#define ADS_DIN_1 P3OUT|=BIT1 //Command write AD
#define ADS_DIN_0 P3OUT&=~BIT1
#define ADS_DIR_OT P2DIR&=~BIT0 //Port is in input mode
#define ADS_CLK_DIR P4DIR|=BIT4 //Port is in output mode
#define ADS_CLK_1 P4OUT|=BIT4 //Clock is set to 1
#define ADS_CLK_0 P4OUT&=~BIT4 //Set clock to 0
#define DIR_BUSY P4DIR&=~BIT0
//#define DATA_IN ((P4IN>>2 & 0x01)
#define DATA_IN (P2IN & 0x01)
#define BUSY_IN (P4IN & 0x01) //Read input data
void Check_busy(void);
void SPI_WR(uchar DATA) ;
void Init_Port(void);
void delay(uint temp);
uint ADS7841_Read_Data(uchar Channel);
uint temp_DATA[100];
void delay(uint temp1)
{
int i;
for(i=temp1;i>0;i--)
{
;
}
}
uint ADS7841_Read_Data(uchar Channel) //Channel=0:CH0;1:CH1;2:CH2;3: CH3;
{
uint ADCResult=0;
uchar i,ADS_CHANNEL;
uint TempBit =0;
uchar COMMAND=0;
switch (Channel)
{
case 0:ADS_CHANNEL=0x10;break; //Channel selection
case 1:ADS_CHANNEL=0x50;break;
case 2:ADS_CHANNEL=0x20;break;
case 3:ADS_CHANNEL=0x60;break;
default:ADS_CHANNEL=0x10;break;
}
COMMAND=(ADS_S|ADS_CHANNEL|ADS_S_D|ADS_POWER);
ADS_CLK_0;
ADS_DIN_0; ///DIN is set to 0 first
ADS_CS_0; //;Chip select signal
//SPI_WR(COMMAND); //SPI bus write command subroutine
//ADS_DIR_IN; //Port is defined as output mode, rising edge sends, falling edge receives
for(i=0;i<8;i++)
{
ADS_CLK_1;
if( (COMMAND & 0x80) ==0x80)
{
ADS_DIN_1; //Write instruction
}
else
{
ADS_DIN_0;
}
COMMAND<<=1; //Left shift
delay(5);
ADS_CLK_0;
delay(5); //Simulate SPI serial interface to send data
}
delay(5);
ADS_CLK_0;
Check_busy();
//delay(5);
for(i=0;i<12;i++)
{ //Rising edge read data
ADS_CLK_0;
delay(4);
if( DATA_IN==0x01 )
{
TempBit=1;
}
else
{
TempBit=0;
}
ADS_CLK_1;
ADCResult=((ADCResult<<1)|TempBit); //Simulate SPI serial interface, receive data
delay(5);
}
ADS_CLK_0;
for(i=0;i<4;i++)
{
ADS_CLK_1;
delay(5);
ADS_CLK_0;
delay(5);
}
ADS_CS_1; //Shield chip select
return ADCResult;
}
void Check_busy(void)
{
int temp;
//DIR_BUSY; //Port is set to input mode
ADS_CLK_1;
temp=BUSY_IN;
ADS_CLK_0;
while( (temp&0x01)==0) //Start reading when high level is detected. . Otherwise, one bit will be lost
{
ADS_CLK_1; //Read port status....
temp=BUSY_IN;
//delay(5); //
ADS_CLK_0;
}
//
/* do
{
ADS_CLK_0; //Read port status....
temp=BUSY_IN;
delay(5); //
ADS_CLK_1;
}while((temp&0x01)!=0); //High bit is 1 for busy signal*/
}
void SPI_WR(uchar DATA)
{
uint i;
ADS_DIR_IN; //Port is defined as output mode, rising edge sends, falling edge receives
for(i=0;i<8;i++)
{
ADS_CLK_1;
if( (DATA & 0x80) ==0x80)
{
ADS_DIN_1; //write instruction
}
else
{
ADS_DIN_0;
}
DATA<<=1; //left shift
ADS_CLK_0;
delay(5); //simulate SPI serial interface to send data
}
delay(5);
ADS_CLK_0;
}
void Init_Port(void)
{
P3SEL=0X00;
P4SEL=0X00;
ADS_DIR_IN;
ADS_DIR_OT;
ADS_CLK_DIR;
DIR_BUSY;
DIR_CS;
ADS_CLK_0;
//delay(5);
ADS_CS_1;
// ADS_CLK_1;
}
void main(void)
{
WDTCTL = WDTPW+WDTHOLD; //turn off watchdog
Init_Port(); //port initialization
uint flag=0;
uint i;
while(1)
{
for(i=0;i<5;i++)
{
temp_DATA[i]=ADS7841_Read_Data(0);
delay(10);
}
flag=1;
}
}
Previous article:Writing of 1S delay program in single chip microcomputer
Next article:Using msp430 and TLC5620 to implement AD_DA
- Popular Resources
- Popular amplifiers
Recommended Content
Latest Microcontroller Articles
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
He Limin Column
Microcontroller and Embedded Systems Bible
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
MoreSelected Circuit Diagrams
MorePopular Articles
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
MoreDaily News
- Wi-Fi 8 specification is on the way: 2.4/5/6GHz triple-band operation
- Wi-Fi 8 specification is on the way: 2.4/5/6GHz triple-band operation
- Vietnam's chip packaging and testing business is growing, and supply-side fragmentation is splitting the market
- Vietnam's chip packaging and testing business is growing, and supply-side fragmentation is splitting the market
- Three steps to govern hybrid multicloud environments
- Three steps to govern hybrid multicloud environments
- Microchip Accelerates Real-Time Edge AI Deployment with NVIDIA Holoscan Platform
- Microchip Accelerates Real-Time Edge AI Deployment with NVIDIA Holoscan Platform
- Melexis launches ultra-low power automotive contactless micro-power switch chip
- Melexis launches ultra-low power automotive contactless micro-power switch chip
Guess you like
- GD32e231 ADC acquisition
- A preliminary study of k210 - MixNo - graphical programming
- 【i.MX6ULL】Driver Development 6——Pinctrl subsystem and GPIO subsystem light up LED
- Audi A6 computer version internal structure analysis, please come and teach me
- Excellent Works of the National College Student Electronic Design Competition - Smart Car Album
- Tektronix RF Communication Laboratory Innovation Experiment Platform
- What is the use of the C language comments in the figure?
- IoT Protocol: MQTT Protocol
- The Development and Application of Wireless Video Surveillance
- PyCorder with capacitive touch matrix