CでArduino Mega 2560のコードを書いていて、シリアルポート経由で双方向通信をしようとしています。ただし、Arduino から PC へのデータの送信のみが機能し、他の方法は機能しません。arduino の RX LED がすぐに点灯しますが、私のコードはデータを受信しません (「ピン 13」に接続されている LED は点灯しません)。これを修正する方法を知っている人はいますか?
arduinoで実行しているコードは次のとおりです。
#define USART_BAUDRATE 500000
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
static void serial_init(void) {
// load upper 8 bits of the baud rate into the high byte of the UBRR register
UBRR0H = (BAUD_PRESCALE >> 8);
// load lower 8 bits of the baud rate into the low byte of the UBRR register
UBRR0L = BAUD_PRESCALE;
// 8data,1stopbit
UCSR0C = (0 << UMSEL00) | (1 << UCSZ00) | (1 << UCSZ01);
// turn on the transmission and reception circuitry
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (0 << UCSZ02);
}
static void sendbyte(uint8_t b) {
// do nothing until UDR is ready for more data to be written to it
while ((UCSR0A & (1 << UDRE0)) == 0) {};
// memory was cleared - write to it
UDR0 = b;
}
static void digi_init() {
// configure port B7 (arduino digital port 13) as output and set it low
PORTB = (0<<PB7);
DDRB = (1<<DDB7);
}
static void digi_set(int val) {
PORTB = (val<<PB7);
}
int main(void) {
serial_init();
digi_init();
while (1) {
if ((UCSR0A & (1 << RXC0)) == 1) {
// we got some data, light up the LED!
digi_set(1);
}
_delay_ms(50);
sendbyte('.');
}
}
PC で実行されているコードは次のとおりです。
int main(int argc, char *argv[]) {
char *serialdevicepath = "/dev/ttyACM0";
fprintf(stderr, "Connecting to serial device ...\n");
int serial_fd = open(serialdevicepath, O_RDWR | O_NOCTTY);
struct termios config;
if(tcgetattr(serial_fd, &config) < 0) exit(1);
config.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON);
config.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
config.c_cflag &= ~(CSIZE | PARENB);
config.c_cflag |= CS8;
config.c_cc[VMIN] = 1;
config.c_cc[VTIME] = 0;
if(cfsetispeed(&config, B500000) < 0 || cfsetospeed(&config, B500000) < 0) exit(1);
if(tcsetattr(serial_fd, TCSAFLUSH, &config) < 0) exit(1);
FILE *serial = fdopen(serial_fd, "r");
setbuf(stdin, NULL);
fcntl(0/*stdin*/, F_SETFL, O_NONBLOCK);
setbuf(stdout, NULL);
setbuf(stderr, NULL);
setbuf(serial, NULL);
while (1) {
char c;
while (read(0, &c, 1) == 1) {
if (c != '+' && c != '-') continue;
uint8_t val = (c == '+') ? 42 : 41;
if (write(serial_fd, &val, 1) != 1) {
assert(0);
}
}
char b = fgetc(serial))&0xe0);
fprintf(stderr, "read 0x%x\n", b);
}
return 0;
}
(そして、はい、データを送信するために PC で <+> と入力しています。また、コードから直接 LED をオンにしてみましたが、うまくいきました。)