您好!
我有一个定制电路、在该电路中、UART (UCA1)和带有 TIMERB0的计数器(TIMERERA0、TIMERERA1)作为计时器模块被同时使用。
TIMERB0模块用于创建1秒中断、TIMERRA0和 TIMERERA1用于对外部脉冲进行计数、UART (UCA1)用于在第二个间隔发送和接收数据、
大多数情况下,操作正常,但在不规则的时间间隔内,传输的数据会丢失,计数值也会超过提供的外部脉冲,如何解决此问题

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.
您好!
我有一个定制电路、在该电路中、UART (UCA1)和带有 TIMERB0的计数器(TIMERERA0、TIMERERA1)作为计时器模块被同时使用。
TIMERB0模块用于创建1秒中断、TIMERRA0和 TIMERERA1用于对外部脉冲进行计数、UART (UCA1)用于在第二个间隔发送和接收数据、
大多数情况下,操作正常,但在不规则的时间间隔内,传输的数据会丢失,计数值也会超过提供的外部脉冲,如何解决此问题

您好、Sasi、
我将不使用 TIMERA0和 TIMERA1开始解决此问题。 只使用 TIMERB0来生成1秒间隔、并在代码中通常读取 TIMERRA0和 TIMERRA1值、而是设置并递增变量、然后传输该值而不是计时器结果。 这将有助于排除 TIMERA0、A1的问题。
此外、您能否尝试将代码减小到可能的绝对最小大小、并查看它是否表明了问题。 这意味着删除代码中除基本功能之外的所有其他内容:TIMERB0用于生成1秒计时、UCA1用于发送数据。 就这些。 这样做可能有助于发现与 TIMERB0或 UCA1无关的问题。
如果您仍然看到问题、则这可能指向您用于传输数据的方法中的某个内容。 您能否共享代码中执行传输的部分?
尊敬的 Dennis:
根据您的建议、我确实只运行计数器和 UART、因此当我尝试运行完整代码时、一切都正常。问题仍然存在、由于设计完成、无法更改微控制器、是否有任何可能的方法来解决此问题。
在这个项目中、使用了两个 ISR、一个用于 TIMERB0、另一个用于 UARTA1、如果两个外设在同一持续时间内中断、任何中断都会下降、
如果其中一个 ISR 需要10ms 来完成其总体操作、那么另一个例程将等待并执行?
您好、Sasi、
好的、这有助于缩小问题的范围。
无需担心同时发生两个不同的中断。 通过查看 MSP430FR5969数据表、表6-4、TI再 培训局的优先级高于 UART1。 这意味着如果两个中断同时发生、中断控制器将确认 TI再 培训中断并跳转到 TI再 培训 ISR。 同时、UART1中断将保持挂起状态(等待)、直到 TI再 培训 ISR 完成、然后调用 UART1 ISR。
由于我们知道 TIMERB 中断每秒发生一次、因此 UART1 ISR 必须是一个最长需要10ms 才能完成的中断、这是有道理的、因为传输数据需要一些时间。 也许此时共享您的代码是有道理的。 可以这样做吗?
尊敬的 Dennis:
我已连接 UART 配置和接收程序
/* GPIO 初始化*/
uint8_t looper9;
P2SEL1 = 0x67;/* UART_A0 RS485_1 GPIO 引脚设置& UART_A1 RS485_2 GPIO 引脚设置*/
PJDIR = 0x30;//禁用缓冲器 IC
PJOUT = 0x20;
P3DIR = 0x80;
P3OUT = 0x00;
/* UART 模块初始化为12MHz */
UCA1CTLW0 = 0x0081;//为 UART 选择 SMclk */
UCA1BRW = 0x0006;//波特率发生器的预分频器置位
UCA1MCTLW = 0x2081;//过采样波特率生成设置为115200波特率*/
UCA1CTLW0 = 0x0080;// UART 模块锁定*/
UCA1IE = 0x0001;
#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector=USCI_A1_vector
_interrupt void USCI_A1_ISR (void)
#endif
{
Receive_buf[0]= UCA1RXBUF;
UCA1IE = 0x0000;/*禁用 UART 中断*
(void) UART_INTERRUPT (receive_buf);
UCA1IE = 0x0001;
}
空 UART_INTERRUPT (uint8_t receive_buff [])
{
uint8_t looper16=0U、rx_buf_1=0U;//初始化缓冲区会导致寄存器中断*/
INT_16T INT_reg;
uint16_t int_reg1;
INT_reg = UCA1IFG;
int_reg1 =(uint16_t) int_reg & 0x0001U;
while ((RX_Buf_1!= 0x21U))
{
LOOOPE16++;
while (!(int_reg1 == 0x0001U)/*轮询是为了创建完美的接收*/
{
INT_reg = UCA1IFG;
int_reg1 =(uint16_t) int_reg & 0x0001U;
}
RX_BUF_1 =(uint8_t) UCA1RXBUF & 0xFFU;//接收 RS485_1的数据*
Receive_buff[looper16]= rx_buf_1;/*读取缓冲区*/
INT_reg1 = 0U;
}
if (logop16 > 3U)
{
(void)命令(receive_buff);
}
其他
{
(void) delay_loop (30);
}
(void) delay_loop (300);
P3OUT = 0x00;/*复位接收使能引脚*
}
您好、Sasi、
我查看了您提供的代码部分。 我看不到任何会导致您出现问题的主要问题。 完全了解这里发生的情况有点令人困惑、因此您可能需要在 TI Resource Explorer 中查看 MSP430FR5969的一些 UART 示例 、看看您是否可以对其进行调整以适合您。 您可能还需要查看 MSP430 Driverlib UART 函数。
您好、Sasi、
好的、我们正在取得进展。
由于 WDT 必须定期复位、我同意您的代码好像卡在例程中。 我的建议是查看任何例程、这些例程"阻止"或等待某个事件发生、例如 IO 引脚发生更改、或等待 UART 中接收下一个字节。 查看所有具有某种形式的"while (1)"循环的代码。
如果这不能帮助解决问题、您可以做的另一件事是将代码最小化到绝对最小值、但仍然证明了这一问题。 很多时候、您会使用这种方法发现问题。
尊敬的 Dennis:
由于我在上面共享了一个代码示例以接收 UART 数据、在该代码中、while 条件用于验证 UART 接收标志、有时代码会滞留在整个程序中、如果单独执行、则不会出现此类问题
while (!(int_reg1 == 0x0001U)/*轮询是为了创建完美的接收*/
{
INT_reg = UCA1IFG;
int_reg1 =(uint16_t) int_reg & 0x0001U;
}
您好、Sasi、
我已重新格式化您的代码、并重新发布、以方便您和可能关注此主题的其他人。
我的第一个注释与您在中断 ISR 内进行的轮询有关。 正如您发现的、轮询中断 ISR 内的任何内容是一种很糟糕的做法。 如果轮询被卡住、您的代码将挂起、或者如果您使用 WDT、器件将最终复位。
我不确定您到底要执行什么操作、但我建议 ISR 中的代码只读取从 UCA1RXBUF 接收到的字节、更新您的 Receive_buff []、然后退出 ISR。 在 main 中执行字节或缓冲区的所有处理。 这样、UART 中断就准备好在接收到下一个字节时生成另一个中断。
为了帮助我了解 UART 接收到的内容、您能否描述预期数据以及您尝试对其执行的操作?
__interrupt void USCI_A1_ISR(void)
{
receive_buf[0] = UCA1RXBUF;
UCA1IE = 0x0000; /* Uart interrupt disabled */
(void)uart_interrupt(receive_buf);
UCA1IE = 0x0001;
}
void uart_interrupt(uint8_t receive_buff[])
{
uint8_t looper16=0U,rx_buf_1=0U; /* initializing buffer leads to drop of registers */
int_16t int_reg;
uint16_t int_reg1;
int_reg = UCA1IFG;
int_reg1 = (uint16_t)int_reg & 0x0001U;
while((rx_buf_1 != 0x21U))
{
looper16++;
while(!(int_reg1 == 0x0001U)) /* polling is done to create perfect reception */
{
int_reg = UCA1IFG;
int_reg1 = (uint16_t)int_reg & 0x0001U;
}
rx_buf_1 = (uint8_t)UCA1RXBUF & 0xFFU; /* receive data for rs485_1 */
receive_buff[looper16] = rx_buf_1; /* Read buffer */
int_reg1 = 0U;
}
if(looper16 > 3U)
{
(void)command(receive_buff);
}
else
{
(void)delay_loop(30);
}
(void)delay_loop(300);
P3OUT = 0x00; /* To reset receive enable pin */
}