Как отправить строку с подчиненного устройства Arduino с помощью SPI?
У меня есть Arduino Uno, выступающий в качестве ведущего, а 3 Arduino Nano выступают в качестве подчиненных.
Глядя на этот пример: http://www.gammon.com.au/forum/?id=10892, он говорит мне, как отправить строку от ведущего устройства к ведомому, но я не видел ни одного примера отправки строки от ведомого устройства к ведущему устройству. Мне удалось успешно отправлять и получать цифры на / от ведущего и ведомого устройств, но я не мог понять, как отправлять строки от ведомого устройства к ведущему, основываясь на примере.
Насколько я понимаю, связь SPI может отправлять информацию только байт за байтом, поэтому должен ли я преобразовать свою строку в байтовый формат, прежде чем помещать ее в переменную SPDR, чтобы ее можно было отправить обратно ведущему?
В любом случае, смогу ли я получить некоторые указания о том, как отправлять строки от ведомого устройства к ведущему?
Заранее благодарю.
@Sam Lee, 👍2
4 ответа
Строка - это только массив символов, заканчивающийся символом \0. Но вы также можете получить к нему доступ в виде массива байтов, заканчивающихся на 0. И отправляйте их по одному байту, пока он не достигнет 0 (отправьте его тоже). На master вы сохраняете его в достаточно длинный массив символов (работайте с ним как с байтами), включая конечный ноль и бинго, у вас есть переданная строка символов :)
Как мне отправить строку из подчиненного устройства Arduino с помощью SPI?
В зависимости от вашего определения строки это будет выглядеть примерно так (для master):
String message = "....";
SPI.transfer(message.c_str(), message.length() + 1);
или
char message[MESSAGE_MAX];
strcpy(message, ....);
SPI.transfer(message, strlen(message) + 1);
Для ведомого устройства SPI это значение необходимо будет преобразовать либо в ISR SPI, либо в busy - дождитесь выбора чипа, а затем передачи.
Ваше здоровье!
Помните, что мастер управляет передачей (обеспечивает синхронизацию), как бы это ни было сделано. Например:
Мастер
// мастер
#include <SPI.h>
void setup (void)
{
Serial.begin (115200);
Serial.println ("Starting");
digitalWrite(SS, HIGH); // убедитесь, что SS остается высоким на данный момент
// Перевести контакты SCK, MOSI, SS в режим вывода
// также переведите SCK, MOSI в НИЗКОЕ состояние и SS в ВЫСОКОЕ состояние.
// Затем переведите оборудование SPI в режим Master и включите SPI
SPI.begin ();
// Немного замедлите работу мастера
SPI.setClockDivider(SPI_CLOCK_DIV8);
} // завершение настройки
void loop (void)
{
char buf [20];
// включить подчиненный выбор
digitalWrite(SS, LOW);
SPI.transfer (1); // инициировать передачу
for (int pos = 0; pos < sizeof (buf) - 1; pos++)
{
delayMicroseconds (15);
buf [pos] = SPI.transfer (0);
if (buf [pos] == 0)
{
break;
}
}
buf [sizeof (buf) - 1] = 0; // обеспечить завершение null
// отключить подчиненный Выбор
digitalWrite(SS, HIGH);
Serial.print ("We received: ");
Serial.println (buf);
delay (1000); // задержка в 1 секунду
} // конец цикла
В этом примере ведущий инициирует передачу, отправляя 0x01 ведомому устройству. Затем он возвращает байты обратно до 0x00 байта (означающего конец строки). Задержка в микросекундах
существует для того, чтобы дать ведомому устройству время для ответа.
Подчинение
// Ведомый
void setup (void)
{
// должны быть отправлены на master in, * slave out*
pinMode(MISO, OUTPUT);
// включить SPI в подчиненном режиме
SPCR |= bit(SPE);
// включить прерывания
SPCR |= bit(SPIE);
} // завершение настройки
volatile char buf [20] = "Hello, world!";
volatile int pos;
volatile bool active;
// Процедура прерывания SPI
ISR (SPI_STC_vect)
{
byte c = SPDR;
if (c == 1) // запуск новой последовательности?
{
active = true;
pos = 0;
SPDR = buf [pos++]; // отправить
return;
}
if (!active)
{
SPDR = 0;
return;
}
SPDR = buf [pos];
if (buf [pos] == 0 || ++pos >= sizeof (buf))
active = false;
} // завершение процедуры обслуживания прерываний (ISR) SPI_STC_vect
void loop (void)
{
} // конец цикла
Подчиненный делает все внутри ISR. Поступление байта 0x01 приводит к сбросу его "указателя" на начало буфера. После этого он отвечает другим байтом из буфера, пока не достигнет конечного байта 0x00.
В части sender я использую метод преобразования строки в массив символов перед отправкой получателю.
Мастер
#include <SPI.h>
const int size_arr = 50; // определяет размер массива (должен быть меньше размера подчиненного устройства)
char buf[size_arr]; // определяет массив символов, используемый для преобразования из строки для отправки подчиненному устройству
String main_dat = "jack,12,47,123,8888"; // реальные строковые данные
void setup() {
pinMode(SS, OUTPUT);
digitalWrite(SS, HIGH);
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV4);
}
void loop() {
main_dat.toCharArray(buf, size_arr); // преобразовать строковые данные в массив символов
Spi_tranmis(buf); // задержка отправки массива символов
delay(500);
}
void send_spi(byte pram) {
digitalWrite(SS, LOW);
SPI.transfer(pram);
digitalWrite(SS, HIGH);
delayMicroseconds(50);
}
void Spi_tranmis(char buf[]) {
for (int i = 0 ; i < size_arr ; i ++) {
send_spi(buf[i]);
}
send_spi('\n');
}
И в части приемника я использую массив символов, получаемый от мастера, и преобразую в строковый символ.
Подчинение
#include <SPI.h>
const int size_arr = 51; // определяет размер массива (должен быть больше размера основного массива)
char buf[size_arr]; // массив символов, используемый для получения от master
volatile byte pos = 0;
volatile boolean process = false;
String msg; // реальные данные
void setup() {
Serial.begin(9600);
Serial.println("test");
pinMode(MISO, OUTPUT);
digitalWrite(MISO, LOW);
SPCR |= _BV(SPE);
SPCR |= _BV(SPIE);
}
ISR(SPI_STC_vect) {
char c = SPDR;
if (pos < sizeof buf) {
if (c == '\n') {
process = true;
}
else {
buf[pos++] = c;
}
}
}
void loop() {
recvHandle();
}
void recvHandle() {
if (process) { // когда SPI доступен
msg = String(buf); // преобразовать массив символов в строку
Serial.println(msg);
process = false;
pos = 0;
}
}
- Вы должны определить размер массива символов в получателе больше, чем в отправителе *
- Отправлять строки через SPI в обе стороны, используя два Arduino UNO (ведущий к ведомому и ведомый к ведущему)
- Как использовать SPI на Arduino?
- Очень простая операция Arduino Uno Serial.readString()
- Как преобразовать строку в массив байтов
- OVF в последовательном мониторе вместо данных
- Проблема совместного использования MISO с несколькими RFID-считывателями RC522
- Понимание того, почему следует избегать «String» и альтернативных решений
- Программирование ведомого SPI для Arduino