PIC 上的 USART 传输问题

发布于 2024-09-24 02:08:24 字数 1460 浏览 13 评论 0原文

我试图从 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

I'm trying to send data to an SD card from a PIC18f4580, but the PIC is not sending what it should be.

related global variables:

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

I am adding data to a buffer using the following function:

void addToBuffer(char data){

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

And putting the data from the TXBuffer into TXREG with the following interrupt:

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
    }

Using an oscilloscope I am able to see that the PIC is sending 0x98, regardless of what I put into the buffer. In fact I never put 0x98 into the buffer.

However, if I replace

TXREG = TXBuffer[TXCurrentPos];

with

TXREG = 0x55;

or

TXREG = TXCurrentPos;

then I get the expected results, that is the PIC will send 0x55 repeatedly, or count up from 0 respectively.

So why does the PIC have trouble sending data from the array, but any other time it is fine? I'll emphasize that transferring is handled in an interrupt, because I feel like that's the root of my issue.

EDIT: It is a circular buffer in the sense that TXEndPos and TXCurrentPos return to 0 when they reach 127.
I also disable the transmit interrupt when TXEndPos - TXCurrentPos == 0, and re-enable it when adding data to the buffer. Really, my code works completely as expected in that if I add 13 characters to TXBuffer in main, my PIC will transmit 13 characters and then stop. The problem is that they are always the same (wrong) character - 0x98.

EDIT2: more complete functions are here: http://pastebin.com/MyYz1Qzq

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

貪欢 2024-10-01 02:08:25

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

您可以在中断处理程序中尝试类似的操作:

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

只是为了向自己证明您可以读取和写入 TXBuffer 并将其发送到 USART。

另请尝试:

TXREG = TXEndPos;

看看这是否符合您的期望(=您的消息长度)。

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

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

另外,您的 main() 似乎突然结束,一旦 main 结束,执行将在哪里继续?

Perhaps TXBuffer doesn't really contain the data you think it does? Maybe you're not calling addToBuffer or calling it at the wrong time or with the wrong parameter?

You can try something like this in your interrupt handler:

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

Just to prove to yourself you can read and write to TXBuffer and send that to the USART.

Also try:

TXREG = TXEndPos;

To see if this matches your expectation (= the length of your message).

I am assuming there's some other code we're not seeing here that takes care of starting the transmission. Also assuming this is done per message with the position being reset between messages - i.e. this is not supposed to be a circular buffer.

EDIT: Based on looking at the more recently posted code:
Don't you need to kickstart the transmitter by writign the first byte of your buffer to TXREG? What I would normally do is enable the interrupt and write the first byte into the transmit register and a quick look at the datasheet seems to indicate that's what you need to do. Another thing is I still don't see how you ensure a wraparound from 127 to 0?

Also your main() seems to just end abruptly, where does the execution continue once main ends?

你的呼吸 2024-10-01 02:08:25

有很多事情你没有照顾到。 TXBuffer 需要是一个循环缓冲区。一旦您将 TXEndPos 增加到超过 127,您就需要将其返回到 0。TXCurrrentPos 也是如此。这也会影响测试缓冲区中是否有东西,> > 0 测试还不够好。一般建议可在此处获取

There are a lot of things you are not taking care of. TXBuffer needs to be a circular buffer. Once you increment TXEndPos past 127 then you need to wrap it back to 0. Same for TXCurrrentPos. That also affects the test to see if there's something in the buffer, the > 0 test isn't good enough. Generic advice is available here.

澜川若宁 2024-10-01 02:08:25

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

使用这种代码架构时通常的做法是,如果没有任何内容要发送(在 IRQ 例程的 else 部分中),则关闭 TXIE,并在 addToBuffer 函数末尾无条件地打开它(因为您随后可以确定至少有一个字符要发送)。

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

Your code is incomplete, but it looks wrong as-is: what happens if there is nothing to send? You don't seem to load TXREG then, so why would anything be transmitted, be it 0x98 or anything else?

The way it is usually done when this kind of code architecture is used is to turn off TXIE if there is nothing to send (in a else part of the IRQ routine), and turn it on unconditionally at the end of the addToBuffer function (since you then know for sure that there is at least one character to send).

Also, you should test TXEndPos and TXCurrentPos for equality directly, since that would let you use a circular buffer very easily by adding two modulo operations.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文