This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TDA4VM: 由于TDA4没有Lin的驱动器,我现在想通过UART来模拟Lin信号,从而进行通讯。

Part Number: TDA4VM


eg.

由于在UART来模拟Lin信号过程中,Lin信号需要 >=13bit的信号,UART无法一次性发送个13bit的数据,我尝试通过降低波特率的方式来实现。

但是,在实现过程中在切换波特率过程比较耗时,导致发送的信号无法连续,从而导致失败。使用的linux的接口代码

static speed_t speed_arr[] = {B230400, B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B600, B300};
static int             name_arr[] = { 230400,  115200,  57600,  38400,  19200, 9600,  4800,  2400,  1200, 600,  300};

static uint32_t uart_fd;

struct serial_t {
    int     fd;
    char    *device;/*/dev/ttyS0,...*/
    int     baud;
    int     databit;/*5,6,7,8*/
    char    parity;/*O,E,N*/
    int    stopbit;/*1,2*/
    int    startbit;/*1*/
    struct termios    options;
};

#define FILE    "/dev/ttyS6"

static struct serial_t __seri_conf[] = {
    [0] = {//connect with b board, ttyS6
        .device = FILE,
        .baud =9600,
        .databit = 8,
        .parity = 'N',
        .stopbit = 1,
    },
    [1] = {//connect with b board, ttyS6
        .device = FILE,
        .baud =19200,
        .databit = 8,
        .parity = 'N',
        .stopbit = 1,
    },
};




/**
 *@brief  设置串口通信速率
*@param  fd     类型 int  打开串口的文件句柄
*@param  speed  类型 int  串口速度
*@return  void
*/
void set_speed(int fd, int speed)
{
  int   i;
  int   status;
  struct termios   Opt;
  tcgetattr(fd, &Opt);
  for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++)
   {
    if  (speed == name_arr[i])
    {
        tcflush(fd, TCIOFLUSH);
        cfsetispeed(&Opt, speed_arr[i]);
        cfsetospeed(&Opt, speed_arr[i]);
        status = tcsetattr(fd, TCSANOW, &Opt);
        if  (status != 0)
            perror("tcsetattr fd1");
        return;
    }
    tcflush(fd,TCIOFLUSH);
   }
}

//设置非标准波特率,比如13292
int serial_set_speci_baud(struct serial_t *tty,int baud)
{
    struct serial_struct ss,ss_set;
    tcgetattr(tty->fd,&tty->options);
    cfsetispeed(&tty->options,B38400);
    cfsetospeed(&tty->options,B38400);
    tcflush(tty->fd,TCIFLUSH);/*handle unrecevie char*/
    tcsetattr(tty->fd,TCSANOW,&tty->options);
    if((ioctl(tty->fd,TIOCGSERIAL,&ss))<0){
        printf("BAUD: error to get the serial_struct info:%s\n",strerror(errno));
        return -1;
    }
    ss.flags = ASYNC_SPD_CUST;
    ss.custom_divisor = ss.baud_base / baud;
    printf("ss.custom_divisor = %d \r\n",ss.custom_divisor);
    if((ioctl(tty->fd,TIOCSSERIAL,&ss))<0){
        printf("BAUD: error to set serial_struct:%s\n",strerror(errno));
        //return -2;
    }
    ioctl(tty->fd,TIOCGSERIAL,&ss_set);
    printf("BAUD: success set baud to %d,custom_divisor=%d,baud_base=%d\n",
            baud,ss_set.custom_divisor,ss_set.baud_base);
    return 0;
}

/*get serial's current attribute*/
static int serial_get_attr(struct serial_t *tty)
{
    if(tcgetattr(tty->fd,&tty->options) != 0){
        printf("SERIAL: can't get serial's attribute\n");
        return -1;
}
    return 0;
}

/*update serial's attrbute*/
static int serial_attr_update(struct serial_t *tty)
{
    tcflush(tty->fd,TCIFLUSH);/*handle unrecevie char*/
    if((tcsetattr(tty->fd,TCSANOW,&tty->options)) < 0){
        return -1;
}
    return 0;
}

static int serial_init_databit(struct serial_t *tty)
{
    if(serial_get_attr(tty)<0)
        return -1;
    tty->options.c_cflag &= ~CSIZE;
    switch(tty->databit){
        case 5: tty->options.c_cflag |= CS5;break;
        case 6: tty->options.c_cflag |= CS6;break;
        case 7: tty->options.c_cflag |= CS7;break;
        case 8: tty->options.c_cflag |= CS8;break;
        default:
            printf("SERIAL: unsupported databit %d\n",tty->databit);
            return -2;    
}
    if(serial_attr_update(tty) < 0)
        return -3;
    printf("SERIAL: set databit to %d\n",tty->databit);
    return 0;
}

static int serial_init_parity(struct serial_t *tty)
{
    if(serial_get_attr(tty)<0)
        return -1;
    /*ignore framing and parity error*/
    tty->options.c_iflag = IGNPAR;
    switch (tty->parity){
        case 'n':
        case 'N':
            /* Clear parity enable */
            tty->options.c_cflag &= ~PARENB;
            /* Enable parity checking */
            tty->options.c_iflag &= ~INPCK;
            break;
        case 'o':
        case 'O':
            /* 设置为奇校检*/
            tty->options.c_cflag |= (PARODD|PARENB);
            /* Disnable parity checking */
            tty->options.c_iflag |= (INPCK|ISTRIP);
            break;
        case 'e':
        case 'E':
            /* Enable parity */
            tty->options.c_cflag |= PARENB;
            /* 转换为偶效验*/
            tty->options.c_cflag &= ~PARODD;
            /* Disnable parity checking */
            tty->options.c_iflag |= (INPCK|ISTRIP);  
            break;
        default:
            printf("SERIAL: unsupported parity %c\n",tty->parity);
            return -2;
}
    if(serial_attr_update(tty) < 0)
        return -3;
    printf("SERIAL: set parity to %c\n",tty->parity);
    return 0;
}

static int serial_init_stopbit(struct serial_t *tty)
{
    if(serial_get_attr(tty)<0)
        return -1;
    switch(tty->stopbit){
        case 1:
            tty->options.c_cflag &= ~CSTOPB;break;
        case 2:
            tty->options.c_cflag |= CSTOPB;break;
        default:
            printf("SERIAL: unsupported stopbit %d\n",tty->stopbit);  
            return -2;    
}
    if(serial_attr_update(tty) < 0)
        return -3;
    printf("SERIAL: set stopbit to %d\n",tty->stopbit);
    return 0;
}

static void uart_init(struct serial_t* seri_conf)
{
    uart_fd = open(FILE, O_RDWR | O_NOCTTY | O_NONBLOCK);
    seri_conf->fd = uart_fd;

    set_speed(seri_conf->fd,seri_conf->baud);


    if(serial_init_databit(seri_conf)<0)
        printf("serial_init_databit error\n");
    if(serial_init_parity(seri_conf)<0)
        printf("serial_init_parity error\n");
    if(serial_init_stopbit(seri_conf)<0)
        printf("serial_init_stopbit error\n");
    //struct termios opt;
    tcgetattr(seri_conf->fd,&seri_conf->options);
    seri_conf->options.c_iflag &=~(BRKINT|ICRNL|INPCK|ISTRIP|IXON);
    seri_conf->options.c_lflag &=~(ICANON|ECHO|ECHOE|ECHONL|ISIG|IEXTEN);
    seri_conf->options.c_oflag &=~(OPOST);
    if(tcsetattr(seri_conf->fd,TCSANOW,&seri_conf->options)!=0)
        printf("error");
}

static int8_t BoardDiag_linSend(uint32_t  fd, uint8_t *writeBuf,
                                uint32_t byteCount)
{
    int8_t  ret = 0;

    ret = write(fd, (uint8_t *)&writeBuf[0], byteCount);
    if(!ret)
    {
        close(fd);
        return -1;
    }

    return 0;
}


static int8_t BoardDiag_linReceive(uint32_t fd, uint8_t *readBuf,
                                   uint8_t byteCount)
{
    int8_t  ret = 0;

    ret = read(fd, (uint8_t *)&readBuf[0], byteCount);
    if(!ret)
    {
        close(fd);
        return -1;
    }

    return 0;
}

typedef struct
{
    uint8_t sync;
    uint8_t pid;
    uint8_t data[7];
    uint8_t checksum;
}linData_t;

void Lin_SendBreak(void)
{
    uint8_t       breakfield1;
    int8_t         status        = 0;
     linData_t      linMasterData;
    //break
    uart_init(&__seri_conf[0]);
    breakfield1 = 0x00;//usigned char breakfield
    BoardDiag_linSend(uart_fd, (uint8_t *)(&breakfield1),
        sizeof(breakfield1));


    close(uart_fd);
    //重置波特率
	uart_init(&__seri_conf[1]);
    set_speed(uart_fd,19200);

     linMasterData.sync              = 0x55;
    linMasterData.pid                 = 0xC1;//PID:0xC1 1100 0001   ID: 0x01
    linMasterData.data[0]         = 0x07;// 0000 0111 
    protectId = 0x01;
    linMasterData.checksum = LIN_MakeChecksum(protectId,sizeof(linMasterData.data),(uint8_t *)(&linMasterData.data));
    
        status = BoardDiag_linSend(uart_fd, (uint8_t *)(&linMasterData),
                                    sizeof(linMasterData));    
    
}

int main(void)
{

    Lin_SendBreak();  
    close(uart_fd);
	return 0;
}

请问:

问题1.在TDA4上通过UART来模拟Lin信号是否是可行的?

如果可行,有什么比较好的方法来降低波特率的切换耗时的问题吗?

如果不行,有什么别的好的方法可以实现呢?

问题2.我用devmem2工具来读取UART4     地址0x02840000寄存器的数据正常,但是我用devmem2工具向寄存器地址0x02840000写值时,提示写入成功,但是重新读取时值未发生改变。

请问这个寄存器是不让修改的吗?