【发布时间】:2019-07-21 23:10:59
【问题描述】:
我在我的 PIC 代码中观察到一些奇怪的行为,我从 由 ISR 写入两个不同缓冲区的全局变量 连续,但该值似乎只成功写入 两个缓冲区之一。当我尝试使用不同的变量时 不是由 ISR 写入的,它会正确地复制到两个缓冲区中。
我的设置是使用 XC8 编译器版本 1.45 的 PIC16LF15355。我是 将 PIC MSSP 模块之一配置为 SPI 接口以写入 测量数据和开关状态到射频收发器。我还有一个 接收和处理数据的远程射频收发器 PIC16LF15355 通过 SPI 接口。对于这两个 PIC,我正在配置 第二个 MSSP 模块作为连接到 Raspberry Pi 的 I2C 接口 调试目的。写入到 SPI 缓冲区的任何数据 发送端也被复制到 I2C 缓冲区,这样就可以 定期阅读以查看正在发送的内容。同样,读取的数据 进入接收端的 SPI 缓冲区被复制到 I2C 缓冲区,所以 可以定期读取它以查看正在接收的内容。
发射端有一个开关输入,用 定时器 ISR(下面代码中的 timer0_handler)。状态被写入 通过此 ISR 进入 sw1State。当需要传输数据时, 开关状态和其他测量数据被复制到 I2C 缓冲区 然后将 I2C 缓冲区复制到 SPI 缓冲区中进行传输。 当我从 Pi 定期对 I2C 缓冲区内容进行采样时,我可以看到 开关状态响应于开关的按下而改变。但是当我 在接收端定期采样 I2C 缓冲区内容,我只 见过开关状态默认值 (1)。
奇怪的是,如果我更改代码以从 不是由 ISR 写入的变量,该值正确显示在 接收端。但是从 I2C 缓冲区复制到 SPI 缓冲区是 只是一个数组到另一个数组的通用副本,以及所有其他测量 数据在接收端正确显示。两个缓冲区应该 相同。我的代码中没有任何东西可以修改 SPI 缓冲区从 I2C 缓冲区复制到 当 SPI 缓冲区被写入收发器时。
代码的精简副本包含在下面。我一直在寻找 在这几天,我只是看不出是什么原因造成的。
volatile uint8_t sw1State; // current switch 1 state
volatile uint8_t sw1TimeExpired; // true if switch 1 debounce time expired
uint8_t spiOutBuf[13]; // SPI output buffer
uint8_t spiInBuf[13]; // SPI input buffer
uint8_t i2cBuff[13]; // I2C input/output buffer
void interrupt main_ISR( void ) {
I2C_slave_handler();
timer0_handler();
switch_input_handler();
}
int main( void ) {
... device initialization code omitted for brevity
sw1State = 1;
sw1TimeExpired = 1;
for ( ; ; )
{
// Read the ADC values and add to the I2C buffer (for debugging).
for ( uint8_t chan = 0; chan < 9; chan++ )
{
i2cBuff[chan + 1] = ADC_read( chan );
}
// Read the switch status and add to the I2C buffer.
i2cBuff[10] = sw1State;
// Load the write transmit payload command into the SPI buffer.
spiOutBuf[0] = CMD_W_TX_PAYLOAD;
// Copy the payload data from the I2C buffer to the SPI buffer.
for ( uint8_t i = 1; i < 13; i++ )
{
spiOutBuf[i] = i2cBuff[i];
}
// Write the SPI buffer to the transceiver module payload register.
writeReadSPI( 13 );
// Clear the RB4 interrupt-on-change interrupt flag (IRQ change) and
// set CE high to initiate the transmit. Hold CE high until an ack
// is received or there is an ack timeout.
IOCBFbits.IOCBF4 = 0;
CE = 1;
__delay_us( 130 ); // ensure minimum state change transition time
... code here omitted which checks the transceiver status
__delay_ms( 80 );
}
}
void switch_input_handler( void ) {
// Check for switch 1 trigger.
if ( IOCCFbits.IOCCF6 == 1 )
{
IOCCFbits.IOCCF6 = 0; // clear IOC interrupt
// Process switch 1 trigger if debounce time has expired.
if ( sw1TimeExpired == 1 )
{
// Toggle between OFF state and ON state.
if ( sw1State == 1 )
{
sw1State = 2;
}
else
{
sw1State = 1;
}
// Load and restart Timer0 with 2-second counter value.
T0CON0bits.T0EN = 0;
TMR0H = 0xc2;
TMR0L = 0xf7;
T0CON0bits.T0EN = 1;
sw1TimeExpired = 0;
}
}
}
void timer0_handler( void ) {
if ( PIR0bits.TMR0IF == 1 )
{
PIR0bits.TMR0IF = 0; // clear the interrupt
T0CON0bits.T0EN = 0; // disable Timer0
if ( sw1TimeExpired == 0 )
{
sw1TimeExpired = 1; // Note the switch 1 timeout for switch handler.
// No state transition here. This just enables
// the next switch interrupt to change state.
}
}
}
void I2C_slave_handler( void ) {
... code omitted for brevity
}
【问题讨论】:
-
你指的是哪个变量,是
sw1State? -
您是否查看了生成的程序集?它可能会给你一些提示。您可以使用 DSO 记录两条 SPI 线路上传输的数据,以查看实际传输的内容。
-
是的,我的意思是 sw1State。感谢您对查看装配的建议。也许正在进行一些优化来解释这一点。我有一个 Bitscope DSO,所以我也可以检查传输的数据。
标签: c embedded microcontroller pic microchip