为什么串行通信只能在一个方向上工作(芯片 - > PC)和我的代码?

时间:2013-01-11 17:12:44

标签: serial-port arduino atmega usart

我正在用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上键入&lt; +&gt;以便它确实发送数据。此外,我尝试直接打开代码中的LED并运行。)

1 个答案:

答案 0 :(得分:2)

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

那个测试是错误的,它永远不会是1.&amp;这里的运算符将产生0或(1 <&lt; RXC0)。反过来赞成它:

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

或者在C中你通常用这种方式写它,因为任何非零值在逻辑上都是正确的:

if (UCSR0A & (1 << RXC0))