USART在PIC上传输问题

时间:2010-09-19 21:50:34

标签: c serial-port microcontroller interrupt pic18

我正在尝试从PIC18f4580向SD卡发送数据,但PIC没有发送它应该发送的内容。

相关的全局变量:

unsigned char TXBuffer[128]; //tx buffer
unsigned char TXCurrentPos = 0x00; //tracks the next byte to be sent
unsigned char TXEndPos = 0x00; //tracks where new data should be put into the array

我使用以下函数将数据添加到缓冲区:

void addToBuffer(char data){

    TXBuffer[TXEndPos] = data;
    TXEndPos++;
}

使用以下中断将来自TXBuffer的数据放入TXREG:

else if (PIR1bits.TXIF == 1){

    if((TXEndPos - TXCurrentPos) > 0){         // if there is data in the buffer
        TXREG = TXBuffer[TXCurrentPos];           // send next byte
        TXCurrentPos++;               // update to the new position
    }

使用示波器我可以看到PIC正在发送0x98,无论我放入缓冲区。实际上我从未将0x98放入缓冲区。

但是,如果我更换

TXREG = TXBuffer[TXCurrentPos];

TXREG = 0x55;

TXREG = TXCurrentPos;

然后我得到预期的结果,即PIC将重复发送0x55,或分别从0开始计数。

那么为什么PIC在从阵列发送数据时遇到问题,但是在其他任何时候都没问题呢?我会强调转移是在中断中处理的,因为我觉得这是我问题的根源。

编辑:它是一个循环缓冲区,TXEndPos和TXCurrentPos达到127时返回0。 我还在TXEndPos - TXCurrentPos == 0时禁用发送中断,并在向缓冲区添加数据时重新启用它。真的,我的代码完全按预期工作,因为如果我在main中向TXBuffer添加13个字符,我的PIC将传输13个字符然后停止。问题是它们总是相同(错误)的字符 - 0x98。

EDIT2:更完整的功能在这里:http://pastebin.com/MyYz1Qzq

3 个答案:

答案 0 :(得分:2)

也许TXBuffer并不真正包含您认为它的数据?也许你没有在错误的时间或错误的参数调用addToBuffer或调用它?

你可以在你的中断处理程序中尝试这样的事情:

TXBuffer[TXCurrentPos] = TXCurrentPos;
TXREG = TXBuffer[TXCurrentPos];
TXCurrentPos++;

为了向自己证明,您可以读写TXBuffer并将其发送到USART。

还可以尝试:

TXREG = TXEndPos;

查看这是否符合您的期望(=邮件的长度)。

我假设还有一些我们在这里没有看到的其他代码负责启动传输。还假设这是根据消息完成的,其中位置在消息之间重置 - 即,这不应该是循环缓冲区。

编辑:基于查看最近发布的代码: 您是否需要通过将缓冲区的第一个字节写入TXREG来启动发送器?我通常做的是启用中断并将第一个字节写入发送寄存器,快速查看数据表似乎表明您需要做的事情。另一件事是我仍然没有看到你如何确保从127到0的环绕?

你的main()似乎只是突然结束,一旦主要结束,执行会继续在哪里?

答案 1 :(得分:1)

有很多事情你没有照顾。 TXBuffer需要是一个循环缓冲区。一旦你将TXEndPos增加到127,那么你需要将它包回到0.相同的TXCurrrentPos。这也会影响测试以查看缓冲区中是否存在某些内容,> 0测试不够好。通用建议是available here

答案 2 :(得分:1)

您的代码不完整,但它看起来不对:如果没有要发送的内容会怎么样?您似乎没有加载TXREG,那么为什么会传输任何内容,无论是0x98还是其他任何内容?

当使用这种代码体系结构时,通常使用的方法是在没有任何内容要发送的情况下关闭TXIE(在IRQ例程的else部分中),然后将其关闭无条件地在addToBuffer函数的末尾(因为你确定至少要发送一个字符)。

此外,您应该直接测试TXEndPosTXCurrentPos是否相等,因为这样可以通过添加两个模运算来非常轻松地使用循环缓冲区。