[讨论] 学艺不精,说说MSP430使用硬件SPI遇到的坑

littleshrimp   2017-4-16 10:07 楼主
这几天在用74HC595驱动8位数码管,之间用CC2541做过驱动都很正常PCB就按照以前的画了,这次单片机使用了MSP430G2553
8位数码管使用2片74HC595驱动,第一片用来显示字符,第二片用来控制哪位显示
调试时发现显示乱码,单字字符显示发现会有篡位的情况,而且显示的效果还和不同的SPI速率和中间的手动延时有关
用示波器测了一下SCLK有DIO引脚,波形正常,数据也正常,因为是2通道示波器就只测了这两个通道的波形
后来反复调试,感觉好像找到规律了,每次结果又都和预想的不太一样
后来又用示波器测量SCLK和RCLK的波形,波形是这样的
image001.png
很明显黄色的RCLK在蓝色的SCLK还在发送数据时就已经设置成高电平(显示更新)
数据还没有发完就更新显示自然就会显示篡位,在发送函数执行后延时一定时间再给RCLK高电平显示正常
显示的问题找到了,剩下就是为什么RCLK在SPI数据还没有发送完成就抬起来了呢?
SPI代码我参考官方提供的msp430g2xx3_uscia0_spi_09.c修改
发送函数spi_write_read_byte在发送前判断UCB0TXIFG是否为1,发送后没有判断
我猜可能是这个问题
  1. uint8_t spi_write_read_byte(uint8_t d)
  2. {
  3. while (!(IFG2 & UCB0TXIFG)); // USCI_A0 TX buffer ready?
  4. UCB0TXBUF = d; // Send next value
  5. return UCB0TXBUF;
  6. }
后来我将代码改成下边这样,发送后再判断是否发送完成
  1. uint8_t spi_write_read_byte(uint8_t d)
  2. {
  3. while (!(IFG2 & UCB0TXIFG)); // USCI_A0 TX buffer ready?
  4. UCB0TXBUF = d; // Send next value
  5. while (!(IFG2 & UCB0TXIFG)); // USCI_A0 TX buffer ready?
  6. return UCB0TXBUF;
  7. }
用示波器测量时发现波形没有任何变化RCLK还是在SCLK时钟没有跑完就抬了起来
原来官方代码的数据发送是在中断函数里实现的,我没有开启中断所以IFG2对应的位不会被更新,判断也就没有实际意义
将代码改成下边这种,通过检查UCB0STAT的UCBUSY判断数据是否发送完成
再测试一切正常
  1. uint8_t spi_write_byte(uint8_t d)
  2. {
  3. while ((UCB0STAT & UCBUSY)); // USCI transmitting or receiving
  4. UCB0TXBUF = d; // Send next value
  5. while ((UCB0STAT & UCBUSY)); // USCI transmitting or receiving
  6. return UCB0TXBUF;
  7. }
image002.png
问题已经解决,另外一个小问题是RCLK上升的速度不够快
如果将时钟频率调的很高,RCLK延时变短就会出现下边情况
image003.png
SCLK的上升速度很快,RCLK像是在给电容充放电
现在还不清楚是MSP430的SPI和GPIO的驱动能力有区别
还是74HC595不同引脚输入电容大小不一样造成的,有空再研究
想起以前使用MSP430G2553这个单片机调试射频模块的情况
当时使用MSP430G2553的GPIO模拟SPI和射频模块通信正常
使用硬件SPI就出错,用示波器比较模拟和硬件的SCLK和MOSI的数据
软件模拟SPI,和硬件SPI发送的数据已经完全一样了,硬件还是不能使用
现在想想那时候硬件SPI发送不成功也许就是因为CS引脚抬起太早导致数据发送中断造成的
时间太长忘了当时没有没测量CS引脚
以前用带逻辑分析仪功能的4通道的示波器没觉得4通道有啥用,后来买示波器时就买了2通道,经过这几次高度发现2通道用起来其实挺别手的
水平不够还容易掉坑里
本帖最后由 littleshrimp 于 2017-4-16 10:09 编辑
虾扯蛋,蛋扯虾,虾扯蛋扯虾

回复评论 (4)

不仅仅是430,所有单片机都是这个规则。
点赞  2017-4-16 12:28
建议硬件控制数据收发,CS自己软件置高置低
点赞  2017-4-16 21:33
引用: lcofjp 发表于 2017-4-16 12:28
不仅仅是430,所有单片机都是这个规则。

刚才又试了一下,判断UCB0TXIFG失败可能和没有设置UCB0RXIE没什么关系比如下边这个延时函数在没有开启CCIE,也可以判断TAIFG
  1. void delay_ms(uint16_t ms)
  2. {
  3.     if(ms > 5957)while(1);
  4.     TA0CTL = TASSEL_1 + MC_0;//stop
  5.     TAR = 0;
  6. //    TA0CCTL0 = CCIE;                                                            // CCR0 interrupt enabled
  7.     TA0CCR0 = 11*ms;
  8.     TA0CTL = TASSEL_1 + MC_1;                                                   // ACLK = 11KHz, Up to CCR0  
  9.     while(!(TA0CTL & TAIFG));
  10. }

虾扯蛋,蛋扯虾,虾扯蛋扯虾
点赞  2017-4-17 10:01
引用: qwerghf 发表于 2017-4-16 21:33
建议硬件控制数据收发,CS自己软件置高置低

那个就是使用硬件收发,软件控制CS
在判断硬件发送是否完成上出了问题,所以没有发送完数据就操作了对应的引脚,比如CS引脚
虾扯蛋,蛋扯虾,虾扯蛋扯虾
点赞  2017-4-17 10:08
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复