| 
 
| 在很久很久以前(40天前),我画了个PCB,主控芯片用的是ADuC7026 然后...一个PCB竟然做了这么久,不得不佩服下这家工厂- -...
 
 好不容易搭好了硬件,没想到软件上又出问题了...花了N天被这个神奇的SPI接口搞得头晕目眩还是没搞定...(下面我附上了连接图)
 
 然后是“症状”:
 我在调试的时候使用Master模式发送,这个地方就比较奇怪了...因为发送对象是2片级联的74HC595,所以要发2个字节,那么我的程序中就这么做了,结果老不正常,然后我意外得发现在末尾跟着发8个“0”就能发送正常(第一个晕倒的地方,到现在还没弄明白..)
 然后是最头疼的Master模式接收,这个还要恶心...我设置成接收的那个8位寄存器满了,中断寄存器里的一个位就置1,然后发3个字节空数据(也就是24个时钟)出去,3片165级联所对应的数据就分3次从MISO读进来了。结果人算不如天算啊,用while去等这个1,然后运行时发现...我这辈子是等不到这个1了T_T...之后没办法,只好在发空数据把165数据从MISO上移进来的时候设置成用while查询发送中断位(就是发送寄存器发光了SPI中断寄存器里就有个1出来)结果这个1我是等到了,然后好不容易读进来数据了,然后又出现那个非常奇怪的问题...很不正常,但是在开头先发1个空字节(8个脉冲)出去,不读,然后再发3个空字节(24个脉冲出去),读3次,这样总算是读进来了,也算正常了。但是好景不长,我惊人得发现~~这个神奇的SPI在同样的输入下,连续快速得读100遍,这数据就不是整体向前就是整体向后移动几位,非常可恶...然后在这100次读函数调用的每个后面都加上while(InputDelay--);后,我又惊人得发现当InputDelay大于40的时候(我是41.78M时钟,延时大于40个周期)读进来的数据是正确的(多少遍都一样),但是没有这个延时,数据就前后移动走样........
 晕啊~~我是郁闷死了ADI你真厉害能制造出这么有创意的SPI接口...
 以下附上我的程序:
 
 /*********************************************************************************************************
 *
 *                                         这个是发送程序
 *
 *********************************************************************************************************/
 
 extern void DOutputWrite(uint32 OutputData)
 {
 SPICON = (1 << 12)|     // Continuous Transfer Enable           1 - Enable                  0 - Disable
 (0 << 11)|     // Loop Back Enable                     1 - Connect test software   0 - Normal mode
 (0 << 10)|     // Slave Output Enable                  1 - Enable                  0 - Disable
 (0 <<  9)|     // Slave Select Input Enable            1 - Enable(Master Mode)     0 - Disable
 (0 <<  8)|     // SPIRX Overflow Overwrite Enable      1 - Overwritten             0 - New byte is discarded
 (0 <<  7)|     // SPITX Underflow Mode                 1 - Transmit 0              0 - Transmit the previous data
 (1 <<  6)|     // Tranfer and Interrupt (Master)Mode   1 - SPITX                   0 - SPIRX
 (1 <<  5)|     // LSB First Transfer Enable Bit        1 - LSB first               0 - MSB first
 (0 <<  3)|     // Serial Clock Polarity Mode Bit       1 - Clock idles high        0 - Clock idles low
 (1 <<  2)|     // Serial Clock Phase Mode Bit          1 - Begin of bit transfer   0 - End of bit transfer
 (1 <<  1)|     // Master Mode Enable Bit               1 - Master mode             0 - Slave mode
 (1 <<  0);     // SPI Enable Bit                       1 - Enable                  0 - Disable
 
 SPITX = ~(OutputData & 0x000000FF);
 while ((SPISTA & 0x02) != 0x02);    // wait for data transfer status bit
 
 SPITX = ~((OutputData & 0x0000FF00) >> 8);
 while ((SPISTA & 0x02) != 0x02);
 
 SPITX = 0x00;                       // 这个就是那邪恶的8个空脉冲
 while ((SPISTA & 0x02) != 0x02);
 
 CLR_595_STR();
 SET_595_STR();
 
 }
 
 /*********************************************************************************************************
 *
 *                                          这个是可恶的接收程序
 *
 *********************************************************************************************************/
 
 extern uint32 DInputRead(void)
 {
 uint32 InputData = 0, InputDelay = 100;
 
 SPICON = (1 << 12)|     // Continuous Transfer Enable           1 - Enable                  0 - Disable
 (0 << 11)|     // Loop Back Enable                     1 - Connect test software   0 - Normal mode
 (0 << 10)|     // Slave Output Enable                  1 - Enable                  0 - Disable
 (0 <<  9)|     // Slave Select Input Enable            1 - Enable(Master Mode)     0 - Disable
 (1 <<  8)|     // SPIRX Overflow Overwrite Enable      1 - Overwritten             0 - New byte is discarded
 (0 <<  7)|     // SPITX Underflow Mode                 1 - Transmit 0              0 - Transmit the previous data
 (1 <<  6)|     // Tranfer and Interrupt (Master)Mode   1 - SPITX                   0 - SPIRX
 (1 <<  5)|     // LSB First Transfer Enable Bit        1 - LSB first               0 - MSB first
 (0 <<  3)|     // Serial Clock Polarity Mode Bit       1 - Clock idles high        0 - Clock idles low
 (0 <<  2)|     // Serial Clock Phase Mode Bit          1 - Begin of bit transfer   0 - End of bit transfer
 (1 <<  1)|     // Master Mode Enable Bit               1 - Master mode             0 - Slave mode
 (1 <<  0);     // SPI Enable Bit                       1 - Enable                  0 - Disable
 
 SET_165_SHIFT();
 CLR_165_CINH();
 
 SPITX = 0x00;                       // 那可恶的8个脉冲又登场了
 while ((SPISTA & 0x02) != 0x02);    // wait for data transfer status bit
 
 SPITX = 0x00;
 while ((SPISTA & 0x02) != 0x02);
 InputData += SPIRX;
 
 SPITX = 0x00;
 while ((SPISTA & 0x02) != 0x02);
 InputData += (SPIRX << 8);
 
 SPITX = 0x00;
 while ((SPISTA & 0x02) != 0x02);
 InputData += (SPIRX << 16);
 
 CLR_165_SHIFT();
 SET_165_CINH();
 
 while(InputDelay--);    //这个地方要等大于40个以上周期,不等就出错,郁闷
 
 return InputData;
 }
 
 /*********************************************************************************************************
 *
 *                                      这个是初始化程序,应该没问题吧..
 *
 *********************************************************************************************************/
 
 extern void DIOInit(void)
 {
 // Set GPIO Mode
 GP1CON &= 0x0FFFFFFF;           // SHIFT_165(P1.7),
 GP2CON &= 0x0FFFF00F;           // CINH_165(P2.7), OE_595(P2.2), STR_595(P2.1)
 
 // Initiatory State
 CLR_165_SHIFT();                // 74HC165 Pin
 SET_165_CINH();
 CLR_595_OE();                   // 74HC595 Pin
 SET_595_STR();
 
 SET_165_SHIFT_OUT();            // GPIO's Direvtion Set
 SET_165_CINH_OUT();
 SET_595_OE_OUT();
 SET_595_STR_OUT();
 
 GP1CON = (GP1CON & 0xF000FFFF) | 0x02220000;
 // MOSI(P1.6), MISO(P1.5), CLK(P1.4)
 SPIDIV = 0x1F;                  // Set SPI clock 40960000/(2×(1+SPIDIV))
 // 0x1F = 625KHz
 }
 
 /*********************************************************************************************************
 *
 *                            这个是测试用的主程序,每个输入和输出都有LED的所以我是直接看它们有没有发光来确定是否读取/发送成功的
 *
 *********************************************************************************************************/
 
 
 int main(void)
 {
 uint32 temp[100], i;
 
 SysClkInit();
 PortInit();
 ADCInit();
 DACInit();
 DIOInit();
 
 DAC_Output(1, 1500);
 DAC_Output(2, 1700);
 
 DOutputWrite(0x0000CCCC);
 Delay_x_ms(500);
 
 DOutputWrite(0x00003333);
 Delay_x_ms(500);
 
 DOutputWrite(0x00005555);
 Delay_x_ms(500);
 
 DOutputWrite(0x0000AAAA);
 Delay_x_ms(500);
 
 for(i = 0; i < 100; i++)
 {
 temp = DInputRead();
 }
 
 while(1)
 {
 for(i = 0; i < 100; i++)
 {
 DOutputWrite(temp);
 }
 }
 }
  | 
 |