且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

基于GCCAVR的TLC2543读写程序----模拟SPI方式实现

更新时间:2022-09-16 17:54:59

TLC2453的操作也比较简单,通过模拟的方式实现只需要看一下时序图把时序搞对即可。

在硬件SPI中,读和写实可以通过硬件同步进行的,因此在写入本次命令字时可以同时读取上一次命令的数据,在模拟SPI的方式中,读和写无法同步进行,因此只能先写后读,读取的即为本次命令的数据。

本程序在测试过程中发现写入命令0x04时读取的数据是正确的,而按照datasheet说明,如果以12位数据方式输出的话低四位应该为1000或者0000,具体原因尚未搞清楚,但是本程序测试是正确的。

程序如下:

hal.h

  1. /**************************(C) COPYRIGHT emouse 2011*************************** 
  2. 名称:hal.h 
  3. 功能:TLC2543测试程序 
  4. 作者:emouse 
  5. 时间:2011.1.11 
  6. 版本:1.0 
  7. 注意:无 
  8. *******************************************************************************/  
  9. #include"avr/io.h"   
  10. #include"avr/interrupt.h"   
  11. #include"util/delay.h"  
  12. #define SetBit(Port,N)  (Port|=(1<<N))    //设置IO某一位   
  13. #define ClrBit(Port,N)  (Port&=~(1<<N))   //清空IO某一位   
  14. #define ReverBit(Port,N)  (Port^=(1<<N))   //取反IO某一位   
  15. #define GetBit(Pin,N)   ((Pin>>N)&0x01)   //读取IO某一位  
  16. /******************************************************************************* 
  17. 名称:void USART0_Init(void)  
  18. 功能:串口0初始化 
  19. 参数:无 
  20. 时间:2011.1.11 
  21. 版本:1.0 
  22. 注意:无 
  23. *******************************************************************************/  
  24. void USART0_Init(void)   
  25. {   
  26. UCSR0A=0x20; //波特率不加倍,单机通信模式   
  27. UCSR0B=0x18; //中断不使能,允许发送和接收   
  28. UCSR0C=0x06;//异步模式,无校验,8位数据,1位停止位   
  29. UBRR0H=0x00;   
  30. UBRR0L=51;//9600波特率   晶振8M  
  31. }   
  32. /******************************************************************************* 
  33. 名称:void USART0_Putc(unsigned char c) 
  34. 功能:发送一个字符 
  35. 参数:unsigned char c 
  36. 时间:2011.1.11 
  37. 版本:1.0 
  38. 注意:无 
  39. *******************************************************************************/  
  40. void USART0_Putc(unsigned char c)  
  41. {  
  42.     while(!(UCSR0A&(1<<UDRE0)));  //等待发送缓冲空   
  43.     UDR0=c;    //发送数据   
  44. }  
  45. /******************************************************************************* 
  46. 名称:void USART0_Puts(unsigned char * str) 
  47. 功能:发送字符串 
  48. 参数:unsigned char * str 待发送的字符串 
  49. 时间:2011.1.11 
  50. 版本:1.0 
  51. 注意:无 
  52. *******************************************************************************/  
  53. void USART0_Puts(unsigned char * str)  
  54. {  
  55.     while(*str)  
  56.     {  
  57.         USART0_Putc(*str++);  
  58.     }  
  59. }  
  60. /***************模拟SPI的相关宏定义********************/  
  61. #define TLC2543_Port PORTC      //设置使用的端口  
  62. #define TLC2543_DDR DDRC  
  63. #define TLC2543_PIN PINC  
  64. #define TLC2543_CS 0            //设置每个信号对应的引脚  
  65. #define TLC2543_MISO 1  
  66. #define TLC2543_MOSI 2  
  67. #define TLC2543_CLK 3  
  68. #define TLC2543_CS_H (TLC2543_Port|=(1<<TLC2543_CS))  
  69. #define TLC2543_CS_L (TLC2543_Port&=~(1<<TLC2543_CS))  
  70. #define TLC2543_GetMISO ((TLC2543_PIN>>TLC2543_MISO)&0x01)  
  71. #define TLC2543_MOSI_H (TLC2543_Port|=(1<<TLC2543_MOSI))  
  72. #define TLC2543_MOSI_L (TLC2543_Port&=~(1<<TLC2543_MOSI))  
  73. #define TLC2543_CLK_H (TLC2543_Port|=(1<<TLC2543_CLK))  
  74. #define TLC2543_CLK_L (TLC2543_Port&=~(1<<TLC2543_CLK))  
  75. unsigned char spi_delay;    //设置信号的持续时间,相当于设置SPI的速度  
  76. /******************************************************************************* 
  77. 名称:void TLC2543_Init() 
  78. 功能:模拟SPI时序的端口初始化工作 
  79. 参数:无 
  80. 时间:2011.1.11 
  81. 版本:1.0 
  82. 注意:无 
  83. *******************************************************************************/  
  84. void TLC2543_Init()  
  85. {  
  86.     TLC2543_Port|=((1<<TLC2543_CS)|(1<<TLC2543_MISO)|(1<<TLC2543_MOSI)|(1<<TLC2543_CLK));  
  87.     TLC2543_DDR|=(((1<<TLC2543_CS)|(1<<TLC2543_MOSI)|(1<<TLC2543_CLK))&(~(1<<TLC2543_MISO)));  
  88.     TLC2543_CS_H;  
  89.     TLC2543_CLK_L;  
  90.     spi_delay=20;  
  91. }  
  92. /******************************************************************************* 
  93. 名称:TLC2543_Send(unsigned char data) 
  94. 功能:发送SPI数据 
  95. 参数:unsigned char data 
  96. 时间:2011.1.11 
  97. 版本:1.0 
  98. 注意:无 
  99. *******************************************************************************/  
  100. void TLC2543_Send(unsigned char data)  
  101. {  
  102.     unsigned char i;  
  103.     TLC2543_CS_L;       //拉低片选信号  
  104.     TLC2543_CLK_L;      //时钟空闲时为低电平   
  105.     TLC2543_MOSI_L;  
  106.     _delay_us(spi_delay);  
  107.     for(i=0;i<8;i++)  
  108.     {  
  109.         if(data&(0x80>>i))//高位在前,低位在前改为(0x01<<i)  
  110.             TLC2543_MOSI_H;  
  111.         else  
  112.             TLC2543_MOSI_L;  
  113.         _delay_us(spi_delay);  
  114.         TLC2543_CLK_H;      //在上升沿更新数据  
  115.         _delay_us(spi_delay);  
  116.         TLC2543_CLK_L;  
  117.     }  
  118.     _delay_us(spi_delay);  
  119.     TLC2543_CS_H;       //拉高片选,完成一次数据传输  
  120. }   
  121. /******************************************************************************* 
  122. 名称:unsigned char TLC2543_Get()  
  123. 功能:接收SPI数据 
  124. 参数:返回data 
  125. 时间:2011.1.11 
  126. 版本:1.0 
  127. 注意:无 
  128. *******************************************************************************/  
  129. unsigned int TLC2543_Get()   
  130. {  
  131.     unsigned char i;  
  132.     unsigned int data=0x000;  
  133.     TLC2543_CS_L;       //拉低片选信号  
  134.     TLC2543_CLK_L;      //时钟空闲时为低电平   
  135.     TLC2543_MOSI_L;  
  136.     _delay_us(spi_delay);  
  137.     for(i=0;i<12;i++)//读取12位ad值  
  138.     {  
  139.         if(TLC2543_GetMISO)  
  140.             data|=(0x800>>i);  
  141.         _delay_us(spi_delay);  
  142.         TLC2543_CLK_H;      //在上升沿更新数据  
  143.         _delay_us(spi_delay);  
  144.         TLC2543_CLK_L;  
  145.     }  
  146.     _delay_us(spi_delay);  
  147.     TLC2543_CS_H;       //拉高片选,完成一次数据传输  
  148.     return data;  
  149. }  
  150. /******************************************************************************* 
  151. 名称:unsigned int Read_TLC2543(unsigned char chan) 
  152. 功能:读取选定通道上的AD值 
  153. 参数:输入参数为需要读取的通道,返回为AD值 
  154. 时间:2011.1.12 
  155. 版本:1.0 
  156. 注意:在硬件SPI中,读和写实可以通过硬件同步进行的,因此在写入本次命令字时可以同时 
  157.       读取上一次命令的数据,在模拟SPI的方式中,读和写无法同步进行,因此只能先写后 
  158.       读,读取的即为本次命令的数据。 
  159. *******************************************************************************/  
  160. unsigned int Read_TLC2543(unsigned char chan)  
  161. {  
  162.     unsigned int adc_data;  
  163.     chan <<= 4;  
  164.     chan |= 0x04;  
  165.     //按照datasheet这里发送的数据低四位应该为0才是以12位数据方式输出,但是测试发现这样发送读取数据是对的  
  166.     TLC2543_Send(chan);  
  167.     adc_data = TLC2543_Get();  
  168.     return adc_data;  
  169. }  

主程序中利用串口读取转换数值进行测试

  1. #include"hal.h"  
  2. #include"stdlib.h"  
  3. unsigned int data;  
  4. unsigned char *s="00000";  
  5. int main(void)   
  6. {      
  7.     USART0_Init();  //初始化USART0接口     
  8.     DDRA=0XFF;  
  9.     PORTA=0XFF;   
  10.     TLC2543_Init();  
  11.     USART0_Puts("SPI test");  
  12.     while(1)   
  13.     {        
  14.         data=Read_TLC2543(0);  
  15.         //USART0_Putc(data);  
  16.         ReverBit(PORTA,0);  
  17.         USART0_Puts(utoa(data,s,10));//转换成字符串输出方便调试。  
  18.         USART0_Puts("/t");  
  19.         data=Read_TLC2543(1);  
  20.         USART0_Puts(utoa(data,s,10));  
  21.         USART0_Puts("/n");  
  22.         _delay_ms(50);        
  23.     }   
  24. }   
 本文转自emouse博客园博客,原文链接:http://www.cnblogs.com/emouse/archive/2011/01/12/2198185.html,如需转载请自行联系原作者