如何利用双缓冲读取数字输入状态?

问题描述

我有以下情况。我有一个微控制器,它通过一个 SPI 外设与两个外部 I/O 扩展器芯片进行通信。每个芯片都有 8 个数字输入,并配备了锁存输入,确保数字输入的两个字节都可以在一个瞬间被采样。要将两个字节的状态传送到我的微控制器中,我需要执行两个 SPI 事务。同时,我需要确保微控制器中的软件可以在两个字节的一致状态下工作。

解决这个问题的第一个想法是使用某种双缓冲区。下面是一段描述我想法的伪代码

library(dplyr)

dd <- mtcars %>% as_tibble() %>% mutate(id = letters[1:32])

identifier <- "d"

is_id <- function(x){
  dat <- dplyr::cur_data_all()
  dat[["id"]] == x
}

dd %>%
  filter(is_id(identifier))

#> # A tibble: 1 x 12
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb id   
#>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
#> 1  21.4     6   258   110  3.08  3.22  19.4     1     0     3     1 d

idenfifiers <- c("a","b")
filter(dd,is_id(idenfifiers))

#> # A tibble: 2 x 12
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb id   
#>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
#> 1    21     6   160   110   3.9  2.62  16.5     0     1     4     4 a    
#> 2    21     6   160   110   3.9  2.88  17.0     0     1     4     4 b

更高的软件层将始终使用 uint8_t di_array_01[2] = {0}; uint8_t di_array_02[2] = {0}; uint8_t *ready_data = di_array_01; uint8_t *shadow_data = di_array_02; uint8_t *temp; if(chip_0_data_received) { *shadow_data = di_state_chip_0; chip_0_data_received = false; } else if(chip_1_data_received) { *(shadow_data + 1) = di_state_chip_1; temp = ready_data; ready_data = shadow_data; shadow_data = temp; chip_1_data_received = false; } 指针指向的数组的内容。我的意图是布尔标志 ready_data (chip_0_data_received) 的设置将在“事务结束”中断中完成,下面的代码将从后台循环以及用于启动SPI 交易。

有人看到我忽略的任何潜在问题吗?

解决方法

如果您的数据总共只有 16 位,您可以原子地读取和写入。

uint16_t combined_data;

// in reading function
if (chip_0_data_received && chip_1_data_received)
{
  combined_data = (((uint16_t)di_state_chip_1 << 8) | di_state_chip_0);
}

// in using function
uint16_t get_combined_data = combined_data;
uint8_t data_chip_1 = ((get_combined_data >> 8) & 0xFF);
uint8_t data_chip_0 = ((get_combined_data >> 0) & 0xFF);