TQ2440 GPIO模拟SPI读取AD转换器TLC2543芯片

转自:http://blog.csdn.net/striker211/article/details/7432685


其实接触CSDN好久了,一直没有想写自己的博客,遇到问题的时候才去上CSDN参考别人的资料,想到以后不能脚踩西瓜皮,滑倒哪里是哪里,要一个萝卜一个坑,用CSDN博客记录下自己的每一个脚印,一来自己以后可以回过来温故知新,二来很高兴为后来人做一个可参考的基石。毕设了,打算用MDK去开发TQ2440,题目是单片机的液压控制系统,其中,会用到TLC2543芯片的AD转换器,TLC2543是12位精度的SPI接口的AD芯片,起初用网上便宜的8位AD芯片PCF8591,好不容易用TQ2440自带的IIC总线调通了AD的读取,老师说精度太低,换!这不,我就选取了TLC2543芯片,原以为调试SPI和IIC一样简单,谁知道,真正调试的时候,遇到各种问题,首先采用的是SPI查询方式,读取的数据一直不确定,检查电路无误之后,上网查遍了S3C2440读取TLC2543的资料,发现资料太少了,唯一可参考的是一位西安交大毕设论文,描述的是linux下的S3C2440的TLC2543读取的驱动的编写。发现了一些错误,但是论文写的遮遮掩掩,并不完全透明。无奈之下,我放弃了SPI接口的编写,网上更多的GPIO模拟的驱动,我搜索了一下,S3C2440的SPI模拟的程序还真没有人写过,我就在此记录一下了。

  1.   
  1. #include "2440addr.h"  
  2. #include "AD.h"  
  3.   
  4. #define CLK(value) (rGPGDAT = (rGPGDAT & ~(1<<11)) | (value<<11)) //CLK  
  5. #define DOUT(value) (rGPGDAT = (rGPGDAT & ~(1<<7)) | (value<<7)) //MOSI   
  6. #define AD_CS(value) (rGPGDAT = (rGPGDAT & ~(1<<10)) | (value<<10)) //AD_CS  
  7.   
  8. /************AD的初始化程序**************************               
  9.     GPG11-----CLK        GPG7----MOSI    
  10.     GPG10-----AD_CS      GPG1-----MISO  
  11.     GPG3----ECO  
  12. ******************************************************/  
  13. void AD_Init(void)  
  14. {  
  15.     rGPGCON&=(~((3<<2)|(3<<14)|(3<<20)|(3<<22)|(3<<6)));    
  16.     rGPGCON|=(0<<2)|(1<<14)|(1<<20)|(1<<22)|(0<<6);   //GPG7,10,11设置成输出,GPG1设置成输入   
  17.     rGPGUP&=(~((1<<1)|(1<<7)|(1<<10)|(1<<11)|(1<<3)));   //只使能GPG1,7,10,11的上拉,做基本IO口  
  18. }  
  19.   
  20.   
  21. void delay_AD(unsigned int N)   
  22. {  
  23. while(N--);  
  24. }   
  25.   
  26. unsigned short Read_AD(unsigned char ADchannel)  
  27. {  
  28.     unsigned int i;  
  29.     unsigned short ADC=0;     
  30.     ADchannel<<=4;  //XXXX 0000,按照格式要求 ,12bits,MSB先入  
  31.     while(!(rGPGDAT&0x0008)); //GPG3----ECO如果是低电平,继续,这里一定要加上,不然可能会出现极大的跳变的现象  
  32.     CLK(0);   
  33.     AD_CS(0);                 
  34.     for(i=0;i<12;i++)  
  35.     {     
  36.         if(rGPGDAT&0x0002)  ADC|=0x0001;//判断接收GPG1的是否为1   
  37.         if(ADchannel&0x80)    
  38.         DOUT(1); //向AD发送数据  
  39.         else DOUT(0);  
  40.         CLK(1);   
  41.         delay_AD(30);                 
  42.         CLK(0);   
  43.         delay_AD(30);  
  44.         ADchannel<<=1;  
  45.         ADC<<=1;   
  46.     }  
  47.     AD_CS(1);  
  48.     ADC>>=1;  
  49.     return ADC;  //12位精度  
  50. }  
#include "2440addr.h"
#include "AD.h"

#define CLK(value) (rGPGDAT = (rGPGDAT & ~(1<<11)) | (value<<11)) //CLK
#define DOUT(value) (rGPGDAT = (rGPGDAT & ~(1<<7)) | (value<<7)) //MOSI 
#define AD_CS(value) (rGPGDAT = (rGPGDAT & ~(1<<10)) | (value<<10)) //AD_CS

/************AD的初始化程序**************************     		
	GPG11-----CLK		 GPG7----MOSI  
	GPG10-----AD_CS		 GPG1-----MISO
	GPG3----ECO
******************************************************/
void AD_Init(void)
{
  	rGPGCON&=(~((3<<2)|(3<<14)|(3<<20)|(3<<22)|(3<<6)));	
	rGPGCON|=(0<<2)|(1<<14)|(1<<20)|(1<<22)|(0<<6);	//GPG7,10,11设置成输出,GPG1设置成输入 
	rGPGUP&=(~((1<<1)|(1<<7)|(1<<10)|(1<<11)|(1<<3)));   //只使能GPG1,7,10,11的上拉,做基本IO口
}


void delay_AD(unsigned int N) 
{
while(N--);
} 

unsigned short Read_AD(unsigned char ADchannel)
{
	unsigned int i;
	unsigned short ADC=0;	
	ADchannel<<=4;  //XXXX 0000,按照格式要求 ,12bits,MSB先入
	while(!(rGPGDAT&0x0008)); //GPG3----ECO如果是低电平,继续,这里一定要加上,不然可能会出现极大的跳变的现象
	CLK(0);	
	AD_CS(0);			  	
	for(i=0;i<12;i++)
	{	
		if(rGPGDAT&0x0002)	ADC|=0x0001;//判断接收GPG1的是否为1 
		if(ADchannel&0x80)	
		DOUT(1); //向AD发送数据
		else DOUT(0);
		CLK(1);	
		delay_AD(30); 				
		CLK(0);	
		delay_AD(30);
		ADchannel<<=1;
		ADC<<=1; 
	}
    AD_CS(1);
	ADC>>=1;
	return ADC;  //12位精度
}








1.上面的程序是参考51的一个例程仿写的,但是51上没有EOC的反馈的连接,我刚开始也没有接,但是读取的数据一直在0和读取数据之间跳变,而且有时候读取的数据还挺奇怪一直怀疑是时序的同步问题,所以我后来加上了EOC的连接,顺利解决的此事,读取数据还算比较稳定。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值