通过串口传输和接收数据(C语言)

hkmswyz6  于 2023-04-11  发布在  其他
关注(0)|答案(1)|浏览(147)

我正在尝试编写一个程序,其中一个部分-也是最重要的部分-程序是使用termios和microship控制器(Atmega 169 P)通过串行端口文件“dev/ttyS 2”建立发送和接收通信。
这个程序有两个方面。一个方面是模拟方面,在这里我通过Cygwin终端运行一个主文件。该文件包含简单的发送和接收终端代码代码应该通过串行文件“dev/ttyS 2”来进行通信。(另一端与微芯片控制器相连)程序的第二端是控制器端,这一端具有通过USART寄存器UDR 0阅读文件的功能(见图2)。它有一个简单的USART_Init()函数来初始化端口,以便正确发送和接收数据。正在发送的数据是简单的位配置(例如0 b 0101)。
图1(模拟侧)

#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

void sendChar(int fd){

    char input = getchar();

    if (input == 'n') {
        uint8_t out = 0b0001;
        write(fd, &out, 1);
    }

    if (input == 's') {
        uint8_t out = 0b0100;
        write(fd, &out, 1);
    }

    if (input == 'e') {
        printf("You have exited the simulation");

    }
    close(fd);
}

void main() {

    int fd;
    fd = open("/dev/ttyS2",  O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd==-1) {printf("Couldn't open specified file");}

    struct termios tty;

    tcgetattr(fd, &tty);
    cfsetospeed(&tty, B9600);
    cfsetispeed(&tty, B9600);
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;
    tty.c_cflag &= ~PARENB;
    tty.c_cflag &= ~CSTOPB;
    tcsetattr(fd, TCSANOW, &tty);

    sendChar(fd);
    }

图2(控制器侧)

#include <avr/io.h>
#include <stdio.h>
#define BAUD 9600
#define F_CPU 8000000UL
#define UBRR_VALUE (F_CPU / (BAUD * 16UL) )

void USART_init(void)
{   // Set baud rate prescaler
    UBRR0H = (UBRR_VALUE >> 8);
    UBRR0L = UBRR_VALUE;
    // Enable receiver and transmitter
    UCSR0B |= (1 << RXEN0) | (1 << TXEN0);
    // Set frame format: 8 data bits, no parity, 1 stop bit
    UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00);
}

unsigned char USART_Receive(void) {
    // Wait for data to be received
    while(!(UCSR0A & (1<<RXC0))); 
    // Get and return received data from buffer
    volatile uint8_t data = UDR0;
    if (UDR0 == 0b0001) {
        writeChar('1',1);
    }
}

int main(){

        USART_init();
    LCD_init();
    
    USART_Receive();
    writeChar('1',5);
            
}

我的第一个测试是看看从模拟端的传输是否工作。为了测试这一点,我放入了图2中所示的代码块,检查寄存器是否具有值“UDR 0 == 0 b 0001”。如果是这种情况,程序将写入(全功能)write_char()函数,该函数将“1”写入微芯片控制器显示器上的位置1(因此也是main中的LCD_Init函数)。正如您可能已经猜到的那样,预期的情况并没有发生。除了调用write_char()在位置5写入“1”的(也是测试)代码外,LCD显示器上似乎没有出现任何东西。
如果您还没有从上述内容中了解到,应该发生的情况是,控制器端应该在LCD显示屏的位置1上写入“1”,以指示发送和接收已连接,并且控制器和模拟端之间的通信正确。

q8l4jmvw

q8l4jmvw1#

那么,我阅读对了吗……你在LCD上的位置5看到一个值“1”?
如果是,则在以下代码中,从USART读取的值不是0b0001(而是UDR0不是0b0001):

unsigned char USART_Receive(void) {
        // Wait for data to be received
        while(!(UCSR0A & (1<<RXC0))); 
        // Get and return received data from buffer
        volatile uint8_t data = UDR0;
        if (UDR0 == 0b0001) {
            writeChar('1',1);
        }
    }

你可能会在UART第一次读取时得到“虚假”数据,我以前在Microchip控制器上遇到过这种情况,我不得不在初始化时执行虚拟读取并丢弃该值。
看起来你可能读到了一个“假”值,这会让你跳出下面的循环:

while(!(UCSR0A & (1<<RXC0)));

但是值不是0b0001。你能在下面的行上设置一个断点吗?

if (UDR0 == 0b0001) {

看看变量数据里有什么
然后,代码继续进行,最终将值“1”放在位置5。

int main(){

        USART_init();
    LCD_init();
    
    USART_Receive(); //Coming out of this function
    writeChar('1',5); //Displaying the value of '1' in position 5
            
}

相关问题