打印

基于pic的spi从动模块的键盘显示例子

[复制链接]
3196|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
machunshui|  楼主 | 2009-7-8 22:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本人写的基于pic的spi从动模块的键盘显示例子。
包括完整工程和proteus仿真图

按键的时候,从机发信号给主机,通知主机接收键值。

主机一次发送10个字节,前8个位数码管显示代码值,后两个为无关数据。
同时接收到的10个数据中,第一个是无关数据,第二个是有效键的个数,后八个为键值.

相关链接:https://bbs.21ic.com/upfiles/img/20097/200978223324785.rar

相关帖子

沙发
machunshui|  楼主 | 2009-7-8 22:37 | 只看该作者

补充说明

补充说明:
proteus的pic的spi模块从动方式有点小bug,
只能设置为:
高电平空闲,第二个时钟沿采样时候才能和proteus的spi虚拟调试器通信,

proteus的spi虚拟调试器要设置为:空闲低电平,第一个时钟沿采样。


不过这不影响程序的逻辑正确性,
要实际使用可以按实际要求更改一下spi的极性和采样边沿

使用特权

评论回复
板凳
古道热肠| | 2009-7-9 16:04 | 只看该作者

谢谢,好东西,帮顶

主动模块很常见,从动设备模块很少见,但有时会用到,比如多单片机系统,用SPI接口通讯就很方便又速度快.

使用特权

评论回复
地板
古道热肠| | 2009-7-9 16:20 | 只看该作者

哈哈,很好,建议加酷,用键盘双缓冲很有趣

void SpiISR(void)
{
    unsigned char temp,i;
    
    if(SSPIF &&SSPIE)
    {
        temp = SSPBUF;
        
    //    SSPBUF = temp;
        if(curSpiRevCnt < MAX_KEY_BUF_LEN+1)
        {
            if(curSpiRevCnt == 0)//切换键盘缓冲区域
            {
                if(curKeyBufID == 0)
                {
                    pSpiSendBuf = (unsigned char *)keyBuf0;
                    curKeyBufID = 1;
                    keyBuf1[0] = 0;
                }
                else
                {
                    pSpiSendBuf = (unsigned char *)keyBuf1;
                    curKeyBufID = 0;
                    keyBuf0[0] = 0;                    
                }        
            }
            
            SSPBUF = *(pSpiSendBuf+curSpiRevCnt);
            
            if(curSpiRevCnt < MAX_DISP_BUF_LEN)//接收前8个字节
                dispBuf[curSpiRevCnt] = temp;
                
            curSpiRevCnt++;    
            if(curSpiRevCnt == MAX_KEY_BUF_LEN+1)
                curSpiRevCnt = 0;
        }
        SSPIF = 0;            
    }    
}


if(bGetKey)
    {
        GIE = 0; //关总中断,防止缓冲区切换过程被中断打断,产生错误
        pBuf = (unsigned char *)(curKeyBufID == 0 ? keyBuf0:keyBuf1);
        GIE = 1;
                    
        curKeyCount = *pBuf;
        if(curKeyCount < MAX_KEY_BUF_LEN)//处理键值
        {
            *(pBuf+curKeyCount+1) = tempKey;
            (*pBuf)++;                            //有效键长度加一
            
            if(curKeyCount == 0)//发送脉冲到主器件外部中断
            {
                RC6 = 1;
                asm("nop");asm("nop");asm("nop");
                RC6 = 0;
            }    
        }
    }        

摘录楼主压缩包中的两段核心代码与大家共赏

使用特权

评论回复
5
古道热肠| | 2009-7-9 16:24 | 只看该作者

双缓冲的确是解决SPI高速向主控器送数的较好办法

使用特权

评论回复
6
machunshui|  楼主 | 2009-7-9 20:11 | 只看该作者

其实I2C德速度也不慢

其实I2C德速度也不慢,但是却可以不用双缓冲,

原因是I2C德通信同步手段比spi丰富.

当从机接受到读地址的时候,

从机在数据发送以前一只拉低时钟,

主机拉不起来时钟,

这样就实现一定程度上的同步.

所以I2C键盘从机发送可以只用单缓冲区.

使用特权

评论回复
7
machunshui|  楼主 | 2009-7-9 20:13 | 只看该作者

用户IO模拟I2C一定要注意

用户IO模拟I2C一定要注意,一定要检测时钟能否拉的起来为高电平,

一定要处理从机时钟延伸,

很多人的模拟I2C的程序都是有问题的.

使用特权

评论回复
8
ayb_ice| | 2009-7-9 20:50 | 只看该作者

LS我认为不一定必要

操作是否成功可以从应答信号判断,不过检查这些信号是个好习惯.

使用特权

评论回复
9
machunshui|  楼主 | 2009-7-9 21:10 | 只看该作者

ayb_ice没看清楚我说的是什么

ayb_ice没看清楚我说的是什么,就开始表达自己的观点了。

主机读的时候,是主机给应答或者非应答信号,

主机检测还啥应答信号啊?

检查自己吗?

使用特权

评论回复
10
ayb_ice| | 2009-7-9 21:28 | 只看该作者

LS

应答信号是由接收数据方发送的好不好,表示接收是否正常,那么主机可以根据这个信号判断通信是否正常.

使用特权

评论回复
11
machunshui|  楼主 | 2009-7-9 21:30 | 只看该作者

对呀

对呀,

主机读的时候,主机是接收方啊,

主机给应答信号啊

使用特权

评论回复
12
古道热肠| | 2009-7-10 15:28 | 只看该作者

SPI接口如同串口,没有复杂协议,只有硬件层的数据交换

所以只能用软件的协议来表示读取到的数据是否有效,楼主的这种双缓冲,且第1字节表示按键数量是较好的方法
如同读SD卡在数据时相时,用FF表示SD卡没准备好,FE时表时准备好数据.
还有一种方式,用硬件中断通知主机.约定好由SPI设备发送到主机的数据内容,读完后释放中断线.很多键盘显示芯片就是这么做的.

SPI数据吞吐量可比I2C大很多.

使用特权

评论回复
13
ayb_ice| | 2009-7-11 10:10 | 只看该作者

但IIC多机通信明显优于SPI

IIC高速也有3.1M的

使用特权

评论回复
14
有风| | 2009-7-11 10:11 | 只看该作者

别人的老婆漂亮,自己的孩子聪明

使用特权

评论回复
15
machunshui|  楼主 | 2009-7-11 10:33 | 只看该作者

各有好处

各有好处.

IIC省管脚,主机程序IO模拟起来麻烦.
spi管脚多,主机程序IO模拟容易

使用特权

评论回复
16
uge| | 2014-12-2 23:20 | 只看该作者
能达到多快的速度

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

153

主题

3224

帖子

4

粉丝