This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
我们在 EK-TM4C129EXL 上运行 TM4C129ENCPDT、并尝试在电路板和运行 PuTTY 的 PC 之间发送和接收字符。
我们正在使用电路板的 ICDI 虚拟 UART、跳线设置正确、并且位于 C:\ti\TivaWare_C_Series-2.1.4.178\examples\boards\ek-tm4c129exl\UART_echo 的 TivaWare 示例程序工作正常。 该程序不使用中断。 它只是在循环中运行、在接收器可用时从接收器读取字符并将其写回发送器。
现在、我们要使用我们基于中断的代码。 接收中断工作正常。 发送中断永远不会被触发。 因此、字符会被正确接收和处理、但字符不会被传输。
如果我们将发送代码从中断处理程序中取出、并将其粘贴到程序的主循环中、则该程序将按预期工作、处理接收的中断处理、但轮询发送的处理。 我们还需要基于中断进行传输。 不仅如此、由于我们不是始终进行传输、而是突发传输、因此我们需要在任何内容被放入软件缓冲区后立即启用传输中断、并且在软件缓冲区变为空时需要将其禁用。 但现在我们只是告诉它始终被启用、只是为了使它正常工作。
我们已经尝试过具有各种水线位的 UARTFIFOEnable()和 UARTFIFOLevelSet(),但这没有什么不同。 我们已经尝试过 UARTFIFODisable(),但这也不起作用。
这是初始化代码:
void SetupUart0 (void)
{
global.SysClockFreqHz = MAP_SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480)、SYSTEM_CLOCK_FREQ_Hz);
SysCtlPeripheralEnable (GPIO_Porta_base);
SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
while (SysCtlPeripheralReady (SYSCTL_Periph_UART0)!= true)
{
}
GPIOPinConfigure (GPIO_PA0_U0RX);
GPIOPinConfigure (GPIO_PA1_U0TX);
GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);
UARTConfigSetExpClk (UART0_BASE、Global. SysClockFreqHz、115200、(UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE | UART_CONFIG_WLEN_8));
//将 UART 设置为在 Tx FIFO 几乎为空或接收到任何字符时中断
//UARTFIFOEnable (UART0_BASE);
//UARTFIFOLevelSet (UART0_BASE、UART_FIFO_TX1_8、UART_FIFO_RX1_8);
IntEnable (INT_UART0);
UARTIntEnable (UART0_BASE、UART_INT_RX | UART_INT_RT | UART_INT_TX);
}
注释代码不能通过 FIFO 尝试不同的操作。
这是中断处理程序:
空 Uart0InterruptHandler (空)
{
uint32_t InterruptFlags;
InterruptFlags = UARTIntStatus (UART0_BASE、false);
UARTIntClear (UART0_BASE、InterruptFlags);
IF (InterruptFlags & UART_INT_TX)
{
// Tx FIFO 中的空间
while (UARTSpaceAvail (UART0_BASE))
{
UARTCharPutNonBlocking (UART0_BASE、BufGet (&Tx));
}
}
IF (InterruptFlags &(UART_INT_RX | UART_INT_RT))
{
// Rx FIFO 中的数据
while (UARTCharsAvail (UART0_BASE))
{
BufPut (&Rx、UARTCharGetNonBlocking (UART0_BASE));
}
}
}
正如我说过的、从中断处理程序中删除带有 UARTSpaceAvail ()和 UARTCharPutNonBlocking ()的 while 循环并将其放入主循环中会使代码正常工作、但随后会轮询发送、而不是基于中断。
初始化后、寄存器包含以下内容:
此处有两种 UART (源自 IIRC、Motorola 和 National Semiconductor)。 如您所述、使用电平敏感中断的中断(如果可能进行传输、则中断始终处于活动状态、必须持续启用/禁用中断)和使用边沿触发中断的中断(中断仅在有发送空间时触发一次、发送过程必须启动传输)。 后一类实际上更多。 电平触发 UART 中断类型仅在 Motorola 很常见。
处理边沿触发中断的方法是在必要时开始传输。 通常称为"注油泵"、原因显而易见。
那么、在发送中断中
例程中
Joseph Campbell 提供了一个旧的 DOS 参考"C 编程人员串行通信指南"、其中对此进行了很好的介绍。 不再适合 PC、但仍然是一个很好的嵌入式参考。
Robert
您好!
您需要以某种方式启动 UART 以生成中断。 您需要先通过所需的中断 FIFO 级别选择对 FIFO 进行一些写入(如果您使用 FIFO 功能)。 例如、您可以配置1/8 FIFO 电平。 这意味着您需要使用两个写入 FIFO 的数据快速启动主系统中的 UART。 一旦两个数据被写入 FIFO、UART 将产生中断。 在 ISR 中、您可以将后续数据写入 FIFO。 如果你不这样做,你就会遇到鸡和蛋的情况。 FIFO 中没有数据、因此没有中断。
实验课程 Lab12中还有一个基于 UART 中断的中断。
另请确保:
IntMasterEnable();//启用处理器中断
[报价用户="Charles Tsaaa">例如,您可以配置1/8 FIFO 级别。 这意味着您需要使用两个写入 FIFO 的数据快速启动主系统中的 UART。 一旦两个数据被写入 FIFO、UART 将生成中断[/引用]
一个人应该足够了,不应该是查尔斯? 至少在我使用过的每个 UART 上、如果不进行审阅、我很确定我的当前 TM4C 代码也是这样做的。 UART 模块不仅在 FIFO 深度低于 FIFO 深度时产生中断、而且在 FIFO 为空时产生中断。
Robert
您好、Robert、
谢谢。 根据数据表、 在 FIFO 模式下、中断是在数据的可编程触发电平被写入后产生的。 如果 FIFO 被禁用、并且发送器中没有数据、那么也会产生中断。 下面是数据表的摘录。
发生以下事件之一时、发送中断将改变状态:
■如果 FIFO 被使能、并且发送 FIFO 在经过编程的触发条件下前进
TXRIS 位被置位。 因此、发送中断基于电平转换
FIFO 必须写入超过设定的触发深度、否则不再发送中断
将会生成。 发送中断通过向发送 FIFO 中写入数据来清除、直到发送 FIFO 中写入数据为止
大于触发电平、或通过向 TXIC 位写1清除中断来清除中断。
■如果 FIFO 被禁用(具有一个位置的深度)、并且中没有数据存在
发送器单个位置时、TXRIS 位被置位。 通过对执行一次写操作可以清除该位
发送 FIFO、或通过向 TXIC 位写1清除中断。
超越"破裂"----这是目前提出的最具酷刑的著作之一。
每个"弯曲"后面都有多个" gotchas "-只是等待我们(轻微)的失误!
虽然有人提到(就在这里/现在)有一个"基于中断的 UART 示例、其中包含在"车间实验室12 "中-是否可以拒绝"在这里为一个合格的、更具(即某种程度上)的可公布/可确定的代码示例"?
这里不是这些(现在)的错-但这应该已经达到(某人的)"待办事项"列表。 (避免并不总是"最佳"选项。)
[引用 user="CB1_MOBILE "]是否可以拒绝"在此处搜索合格的、更多(即某种程度上)已公布/可确定的代码示例"? [/报价]
事实上,这样一个例子应该能够说明如何处理以下情况
Robert
至少接收超时模式很容易处理。
与我使用过的每一个 UART 不同、TI 将接收超时分离为不同于接收中断的单独中断。 您只需将其视为接收中断即可。
IE 开关(状态) 案例 Receive_timeout: 案例接收: (笑声) 中断;
如此简单、出乎意料。
我没有看到这种分离的有用应用,尽管有人试图提出正当理由。
Robert
Robert Adsett 说:嗯、这是坏的。 很高兴您提请我注意。 使用 EOT 触发器时有一些变通方法。[/QUERT]
实际上、解决此问题的唯一方法是将发送中断更改为在传输结束时触发。 可能会使通信量略有增加、但您不应错过发送中断、您仍然可以使用接收 FIFO。 到目前为止、我还没有看到任何其他保证工作的东西。
Robert
[引用 user="12ve12pm"]如果在中断结束时有一个额外的中断,那么是否可以启用这两个中断并为它们提供相同的处理方式,就像"接收模式"一样?
不是我能看到的。 EOT 中断替代 FIFO 阈值中断。 如果它是额外的、它将解决大部分问题。 因为这是我唯一能看到的工作情况、但性能会有轻微下降。 在许多不太可能重要的应用中。
可能会忽略中断吗?
Robert
在某种程度上,我们"囚犯"(似乎)是在管理庇护的(有些)吗? 这是否能够证明是最佳的?
是否敢问、"在这里、需要"UART 架构/管理"专家?"
[引用 user="12ve12PM">更重要的是、您是否在 TM4C 上使用了 DMA 和 UART? [/报价]
不、鉴于串行通信的性质、我从未见过这样一个有意义的案例(考虑如果一个字节被丢弃或被添加会发生什么情况)。
[引用 user="12ve12pm">但我们已准备好旋转具有多个 TM4C 的电路板、该 TM4C 通过 UART 相互通信。 我不确定确切的数字、但我想他们会每秒交换1千字节的数据、每秒100次、我希望以4 MHz 的频率运行 UART。[/引述]
什么类型的数据? 您确定可以获得4MHz 收发器吗?
Robert
[引用用户="Charles Tsaaaa">当 UARTCTL 寄存器的 EOT 位置位时、一旦 FIFO 完全为空且包括停止位在内的所有数据都已离开移位寄存器、就会产生发送中断。 [/报价]
是的。 我曾经使用过的所有其他 FIFO 的 UART 都提供了一个在 FIFO 清空时发生的中断。 TI 不提供此类服务是例外。
[引用用户="Charles Tsaa"]。 要生成 EOT 中断、您仍需要首先将一个数据写入主函数中的 FIFO。[/QUERP]
当然、与所有其他边沿触发 UART 一样
[引用 USER="Charles Tsaa"]但您是对的。这是另一种通过使用 EOT 而不是 FIFO 阈值来继续基于中断的重新传输的方法。[/引用]
我可以说、这是唯一安全的方法。 至少没有提出其他安全方法。
Robert
我更想了解数据和命令的类型以及重复的数量。 该带宽超过饱和可能、但如果有足够的重复流量、则可能适合该带宽。 我还听说有人使用以太网来处理这种流量。
不过、我想知道要使用的接口是否不是 FIFO、甚至可能是共享存储器。 这样就会获得很大的带宽、但您必须为 FIFO IC 付费。
解释了为什么您不担心收发器、尽管我想检查开销。
Robert
[引用 user="12ve12pm"]……数据表显示您可以将 UART 启动至7.5MHz[/quot]
然而、如果不提及任何添加的"错误率"或(实际)操作条件、或数据有效载荷、此类索赔可能无法证明是完全令人信服的。
曾担任过工程经理。 在一个"类似的、半巨人"的场合、有人指出、"乐观的发现"是在"远程设备(完美)"处于"拨入"状态(即精心设置的频率)时产生的、而这种情况不会与您的情况重叠。 此外、在现实世界中、一个 MCU 可以"快速运行"、另一个 MCU "缓慢"、那怎么办? (此类频率误差是累加的)
和-由"PVT"(过程变化、电压、温度)和简单老化强制执行的偏差-必须预先考虑-和防护带。 所有这些都需要(更加)保守的方法-以及可靠的测试/验证。
在4MHz 频率下、我们发现电路板布局非常重要-短距离、直接布线以及与其他潜在影响信号的良好"分离"-所有这些都"推动您取得成功"。 然而、"注意"应该靠近、 数据完整性应该高速。
另请注意-此处(较小)的 MCU (4C123)通常在 TX 线路上需要"上拉 R"、这可能会影响最大速度... (此类需求也可能会溢出到您的设备中...)
[引用 user="12ve12pm"] UART 对每个位进行16次采样
我是否可以不同意-我相信(只是) 3个这样的"投票样本"是"选择的样本"。 (这个议题是最近提出的(这里)--我记得"3"数字----这是(最后)商定的。)
您"抓住"上拉-但您的"对速度的需求"-减去精心选择的"注意事项"-似乎没有什么顾虑-警报...
至于 UART (异步)与 SPI (同步)、我会每次投票选择时钟数据(几乎)。 回忆一下我之前的帖子-您的互联 MCU 之一可能"快速"运行-而另一个则"缓慢!" 这如何提高可靠性? 容忍"额外"信号线(即数据时钟)这一事实必须用"SPI"表示某种优势、即"信号可靠性/稳健性!"
您可以通过调查"附件 IC"的出现情况(为每种串行格式提供服务)、深入了解"SPI 与 UART 的价值"。 SPI -压倒性优势-获胜! (" 宰杀规则"经常被称为...)
我应该注意到、FIRM/I 是 UART 的"风扇"、尤其是当通信流过(超过)电路板时、并且部署了适当的收发器/电平转换器(甚至无线电模块)。
[引用 user="12ve12pm"]我看不到使用发送中断的任何好处。
只需在这次漫长的对话中添加我的两分...
我们实施的方式、并且我理解、缓冲器传输控制器必须注意:
-是否仍有字节要发送(从缓冲区到 FIFO)
如果有空间将字节放入 FIFO 中
因此、我发现不需要 EOT 中断!
假设您有3个字节要传输、FIFO 为空。 传输控制器会像 while 那样执行某项操作(FIFO_FASH_ING_INOPEN_BUSCK_RED_TO_BE_BE_SENT);
这三个字节将立即发送、故事结束。 这适用于1个字节、16个字节、等等。 由于缓冲器已完全传输、环路将退出、因此在应用程序端不必再担心、它可以假设"所有数据都已传输"。 您真的需要知道、这里最后一个字节实际上离开了硬件吗? 正确的传输需要其他方法、确认协议等。
现在、假设您有25个字节。 前16个字节将立即发送、您可以返回到 MCU 需要执行的任何操作-您将在这些字节的"部分"离开 FIFO 后获得中断(例如、其中一半字节在默认配置下)。 当您获得该中断时、您有一些时间为其提供服务、只需使用相同的逻辑再次调用该"控制器"即可。 当您开始发送剩余的9个字节时、很可能会有一个额外的字节离开硬件、因此所有9个字节都将在第二个调用中消失。 否则、没有问题-最后一个字节将在控制器的第三次调用中简单地发送。
微调中断的 FIFO 水平。 如果在离开 FIFO 2个字节后立即设置中断、您将经常调用控制器。 如果您将其设置为在剩余14个字节后中断、您将在下一个控制器调用中获得"大量 FIFO 空间"的好处-但如果您的代码正忙于执行其他操作、 您可能会浪费传输时间、因为最后2个字节在您能够发送更多字节之前已发送。
使用流程图可以更容易地解释这一点,但我希望文本是有意义的。 我们发现、此类策略提供了非常可靠的 UART 传输、不会与接收端发生混乱、也不需要太多的处理。
布鲁诺
[引用用户="Bruno Saraiva"]
我们实施的方式、并且我理解、缓冲器传输控制器必须注意:
-是否仍有字节要发送(从缓冲区到 FIFO)
[/报价]
这是我认为的部分、总的来说很难做到。 实际上、我通常唯一能看到的方法是添加一个计时器、以减少字符留在 FIFO 中的时间。 依靠概率只会使您很难跟踪错误。
[引用用户="Bruno Saraiva"-如果有空间将字节放入 FIFO 中
此器件很普通
[引用 user="Bruno Saraiva">假设您有3个字节要传输、FIFO 为空。 [/报价]
第一个问题、您如何知道 FIFO 为空?
[引用 user="Bruno Saraiva"]三个字节将立即发送,结束故事
只是故事的开始。 第二个问题何时/将触发中断? 如果您向队列中添加更多字符、您是否需要将它们发送到 FIFO、或者是否可以依赖中断?
[引用用户="Bruno Saraiva"]。 您真的需要知道、这里最后一个字节实际上离开了硬件吗? 正确的传输需要其他方法、确认协议等。
您还如何知道何时向 FIFO 中添加更多字节?
[引用 user="Bruno Saraiva">现在、假设您有25个字节。 前16个字节将立即发送、您可以返回到 MCU 需要执行的任何操作-您将在这些字节的"部分"离开 FIFO 后获得中断(例如、其中一半字节在默认配置下
是的
[引用 USER="Bruno Saraiva"]当您得到该中断时,您有一些时间来为它提供服务,只需再次使用相同的逻辑调用该“控制器”即可。 当您开始发送剩余的9个字节时、很可能会有一个额外的字节离开硬件、因此所有9个字节都将在第二个调用中消失。
一般而言、依赖概率并不会导致可靠的软件。
[引用 USER="Bruno Saraiva"]如果不是,没有问题-最后一个字节将在控制器的第三次调用中发送。
好的、如果您在最后一个字节离开队列后立即排队等待另外3个字节、会发生什么情况?
如果在 FIFO 中断触发后立即排队3个字节、会发生什么情况?
我想我看到一两种方法可以解决这个问题、但需要注意防止比赛条件。
Robert
[引用 user="Robert Adsett"](-是否仍有要传输的字节(从缓冲区到 FIFO)。 我认为这一部分一般很难做到。[/引述]
不客气。 您误解了。 控制器需要知道缓冲区中是否有挂起的字节、这些字节需要放置在 FIFO 中。 当它们处于 FIFO 中时、任务就完成了。 那么、这只是一个缓冲指针问题。
[引用 user="Robert Adsett"]第一个问题:如何知道 FIFO 为空?
就该示例而言、从定义上讲、它是空的。 为了知道 FIFO 是空的、我们有这个奇怪的东西、我甚至不想重新理解:
(!(HWREG (Serial_UART[uarted][serial_base]+UART_O_FR)和 UART_FR_TXFF))
[引用 user="Robert Adsett"]您还如何知道何时向 FIFO 中添加更多字节?[/quot]
在收到 TX 中断后、您可以立即向 FIFO 添加更多字节! 同样、您不需要知道是否所有字节都通过了线缆。
[引用 user="Robert Adsett"]好的,如果您在最后一个字节离开队列后立即再排队3个字节,会发生什么情况?[/quot]
您永远不会排队3个字节、8个字节或任何字节。 当 FIFO 中有空间时、您会逐个排队。 您可以控制缓冲区的指针:一个指向已发送到 FIFO 的内容、另一个指向需要发送的最后一个字节。
[引用 user="Robert Adsett"]依赖概率通常不会导致强大的软件。
这是一个平均评价! 你在阅读其余的之前写的!!! 反对!!!!
希望这些附加的注释能清除一些问题!
布鲁诺
[引用用户="Bruno Saraiva"]
就该示例而言、从定义上讲、它是空的。 为了知道 FIFO 是空的、我们有这个奇怪的东西、我甚至不想重新理解:
(!(HWREG (Serial_UART[uarted][serial_base]+UART_O_FR)和 UART_FR_TXFF))
[/报价]
是否没有一个能做到这一点的整洁 TivaWare 函数?
[引用 user="Bruno Saraiva">就本示例而言,它按定义为空。 [/报价]
这是我的观点。 您必须同时考虑空和非空条件。 您只考虑了空条件。
[引用 user="Bruno Saraiva"]要知道 FIFO 是空的,我们有这个奇怪的东西,我甚至不想重新理解:
这决定了是否会发生中断、因此必须绝对考虑该条件及其影响。
[引用用户="Bruno Saraiva"]
Robert Adsett一般而言、依赖概率并不会导致可靠的软件。
[/报价]
我是这样做的。
[引用用户="Bruno Saraiva"]
Robert Adsett好的、如果您在最后一个字节离开队列后立即排队等待另外3个字节、会发生什么情况?
[/报价]
这不能回答问题。 它会在不寻址的情况下将其侧翻。
我提到过、我认为我看到了一个清晰的方法、我认为我确实做到了。 它确实需要一些工作来避免竞争、与传统 UART FIFO 相比、这会显著增加延迟
首先从传统 UART 开始
应用程序代码
TransmitByte (char byte) { 如果 PrimePumpFlag set 为、则向队列添加字节{ 禁用中断 将字节放入 UART FIFO 清除 PrimePumpFlag 启用中断 } }
在某些情况下、您可以在启动时放弃中断保护。 不过、如果您希望防止将来发生更改、那么即使现在适用这种情况、中断保护也应该仍然存在。 请注意、此处的操作顺序很重要。
中断代码
UARTTransmit() { 如果! queue_empty{ 将队列复制到 FIFO,直至队列为空或 FIFO 已满 } 否则{ 设置 PrimePumpFlag } }
这将不适用于 TI UART、因为在未填充 UART FIFO 超过 FIFO 阈值的情况下、将不会发生中断、并且将永远不会设置 PrimePumpFlag、因此传输永远不会重新开始。
修复此问题的简单安全方法是将发送中断转换为 EOT 中断、并使一些话务员带宽损失。 不过,我认为我有一个更好的方法。
从中断代码开始。 它实际上简化了、因为无法设置启动标志。
UARTTransmit() { 如果! queue_empty{ 将队列复制到 FIFO,直至队列为空或 FIFO 已满 } }
应用代码现在需要额外的保护、至少可以说更复杂
TransmitByte (char byte) { 如果 队列为空且!FIFO 已满,则禁用中断{ 将字节放入 UART FIFO } 否则{ 将字节添加到队列 } 启用中断 }
扩大保护期是防止种族状况的必要条件。 我认为我没有留下任何比赛条件、但需要回顾一下、我只是对它进行了初步检查。
它的两个副作用
关于中断保护的注释、只要发送的优先级永远不会高于发送中断、那么禁用只需要阻止发送中断。 如果不是、禁用必须更具包容性、并且中断代码中也需要额外的块。
Robert
[引用 USER="Bruno Saraiva"]由于这个中断,它必须检查 FIFO 空间
只需进行 FIFO 完全检查。 请参阅 UARTSpaceAvail。 应归结为简单的标志检查。
Robert
[引用 USER="CB1_MOBILE "]
您"抓住"上拉-但您的"对速度的需求"-减去精心选择的"注意事项"-似乎没有什么顾虑-警报...
至于 UART (异步)与 SPI (同步)、我会每次投票选择时钟数据(几乎)。 回忆一下我之前的帖子-您的互联 MCU 之一可能"快速"运行-而另一个则"缓慢!" 这如何提高可靠性? 容忍"额外"信号线(即数据时钟)这一事实必须用"SPI"表示某种优势、即"信号可靠性/稳健性!"
[/报价]
现在我很紧张!
关于同步通信优势的观点。 (顺便提一下、您对 USART 有什么看法? 它可以为您提供组帧和时钟! TM4C 太糟糕了。)
我必须进一步研究、并运行一些测试...
[引用 user="12ve12PM"]意外地、您对 USART 有何看法? 可为您提供组帧和时钟![/引述]
真的、有一个指针? 我看到的所有 USART 都不在同步模式中提供任何组帧(我认为这有点像一个催产的组帧)。 它们只是一种提供类似 SPI 接口的方法。
Robert
布鲁诺,我的最后一个回答有点偏。 我想你写错了。
但是 、FIFOEMpty 和 SpaceAvailable 有很大不同。 实际上、您可以使"可用空间"与 SpaceUSED 更接近(而不是 FIFOEMpty)。 考虑16字节 FIFO
逻辑反向关系
FIFO 满标志是现成可用的标志、也是您所检查的标志。
我怀疑可以通过检查发送保持寄存器是否为空来近似计算 FIFO 为空、但我尚未验证标志是否可用。
Robert