0

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 をオンにしてみましたが、うまくいきました。)

4

1 に答える 1

2
if ((UCSR0A & (1 << RXC0)) == 1) 

このテストは間違っています。1 になることはありません。ここでの & 演算子は、0 または (1 << RXC0) のいずれかを生成します。代わりに、次の方法をお勧めします。

if ((UCSR0A & (1 << RXC0)) != 0) 

または、C では通常、ゼロ以外の値は論理的に真であるため、次のように記述します。

if (UCSR0A & (1 << RXC0)) 
于 2013-01-11T18:47:59.733 に答える