问题描述
我有以下情况。我有一个微控制器,它通过一个 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);