串行读/写/开发/tty检查



我正在尝试将PIC24 uC与在Linux上运行的Armadillo IoT Gateway连接起来。我已经阅读了以下线程:如何读取/写入tty*设备?

但是当我被告知要避免在那里提问时,我打开了一个新的:/

根据设备手册,RS232C连接器的TTY设备文件是/dev/ttymxc3.如果我正确理解了上面的线程,当通过相应的连接器连接外部设备时,可以从/dev/tty* 文件中读取发送的数据吗?因此,作为程序员,我不必考虑缓冲区等。

我现在通过以下方式更新了网关的主代码:

FILE *dental_unit_data; //new
int main(void)
{   
//existing, non relevant code...
//new; data acquisition 
dental_unit_data = fopen("/dev/ttymxc3", "r"); 
ctl_auto_du(dental_unit_data); //reads the data from the dental_uni_data 
//file. Then sends the acquired data to the database.

下面提供了 ctl_auto_du(int *fd( 的源代码。 真的那么简单,还是我从根本上误解了什么?

int ctl_auto_du(int *fd) 
{
//int result,err,sig;
size_t count = 0;
unsigned char wcmd[SP_WRITE_BUF_SIZE];
size_t wsize;
unsigned char rcmd[SP_READ_BUF_SIZE];
size_t rsize;
Event_t events[TYPE_COUNT];
size_t event_count;
CtlLog_t ctl_log;
long long int now_ms;
memset(events,0x0,sizeof(Event_t) * TYPE_COUNT); //events has 34 entries, put 0x0 inn all of those
//struct timeval tv_now;
//char *dataArr[50];
//double tmpd;
//int seisu;
//int i;
DU_t *latest_du;
//起動時に全ID

while (TRUE) {
system(LED_DU_OFF);
//int idx = 0;
memset(&latest_du,0x0,sizeof(latest_du));
memset(wcmd,0x0,sizeof(wcmd));
memset(rcmd,0x0,sizeof(rcmd));
wsize = 0;
rsize = 0;
if (g_do_forced_termination == TRUE) {
fprintf( stderr, "!!!Ctl DU Thread Forced termination !!!n");
break;
}
//受信
count = recv_du(fd, rcmd); //rcmd = receive buffer, stores read bytes
if (count > 0) {
memset(events,0x0,sizeof(Event_t) * TYPE_COUNT);
memset(&ctl_log,0x0,sizeof(CtlLog_t));
event_count = 0;
wsize = 0;
now_ms = get_now_milliseconds();
system(LED_DU_ON);
rsize = count;
printf("ctl_du read size[%d]n", rsize);
printf("ctl_du_cmd read datan");
printf_hex(rcmd, rsize);
latest_du = (DU_t *)rcmd;
ctl_log.ins_datetime.ullint = now_ms;
memcpy(ctl_log.data.bytes,rcmd,10); //「歯科機器 -> ArmadilloIoT」のデータ;
insert_ctl_log(ctl_log); //int return value; will give unused warning //save ctl_log to DB
if (latest_du->func_cd.uchar == 0x44) {  //check function code; 0x44==D --> if contains data:
//D, g_latest_du filled with 0x0 during main call.
if (g_latest_du.byte0.bf.id00 != latest_du->byte0.bf.id00) { //first bit of first byte; checks if id is set
events[event_count].eve_datetime.ullint = now_ms;        // and thus being used.
events[event_count].eve_type_num.uchar = 0;
events[event_count].eve_eve_cd.uchar = latest_du->byte0.bf.id00;
event_count ++;
}
if (g_latest_du.byte0.bf.id01 != latest_du->byte0.bf.id01) { 
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 1;
events[event_count].eve_eve_cd.uchar = latest_du->byte0.bf.id01;
event_count ++;
}
if (g_latest_du.byte0.bf.id02 != latest_du->byte0.bf.id02) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 2;
events[event_count].eve_eve_cd.uchar = latest_du->byte0.bf.id02;
event_count ++;
}
if (g_latest_du.byte0.bf.id03 != latest_du->byte0.bf.id03) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 3;
events[event_count].eve_eve_cd.uchar = latest_du->byte0.bf.id03;
event_count ++;
}
if (g_latest_du.byte0.bf.id04 != latest_du->byte0.bf.id04) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 4;
events[event_count].eve_eve_cd.uchar = latest_du->byte0.bf.id04;
event_count ++;
}
if (g_latest_du.byte0.bf.id05 != latest_du->byte0.bf.id05) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 5;
events[event_count].eve_eve_cd.uchar = latest_du->byte0.bf.id05;
event_count ++;
}
if (g_latest_du.byte0.bf.id06 != latest_du->byte0.bf.id06) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 6;
events[event_count].eve_eve_cd.uchar = latest_du->byte0.bf.id06;
event_count ++;
}
if (g_latest_du.byte0.bf.id07 != latest_du->byte0.bf.id07) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 7;
events[event_count].eve_eve_cd.uchar = latest_du->byte0.bf.id07;
event_count ++;
}
if (g_latest_du.byte1.bf.id08 != latest_du->byte1.bf.id08) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 8;
events[event_count].eve_eve_cd.uchar = latest_du->byte1.bf.id08;
event_count ++;
}
if (g_latest_du.byte1.bf.id09 != latest_du->byte1.bf.id09) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 9;
events[event_count].eve_eve_cd.uchar = latest_du->byte1.bf.id09;
event_count ++;
}
if (g_latest_du.byte1.bf.id10 != latest_du->byte1.bf.id10) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 10;
events[event_count].eve_eve_cd.uchar = latest_du->byte1.bf.id10;
event_count ++;
}
if (g_latest_du.byte1.bf.id11 != latest_du->byte1.bf.id11) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 11;
events[event_count].eve_eve_cd.uchar = latest_du->byte1.bf.id11;
event_count ++;
}
if (g_latest_du.byte1.bf.id12 != latest_du->byte1.bf.id12) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 12;
events[event_count].eve_eve_cd.uchar = latest_du->byte1.bf.id12;
event_count ++;
}
if (g_latest_du.byte1.bf.id13 != latest_du->byte1.bf.id13) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 13;
events[event_count].eve_eve_cd.uchar = latest_du->byte1.bf.id13;
event_count ++;
}
if (g_latest_du.byte1.bf.id14 != latest_du->byte1.bf.id14) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 14;
events[event_count].eve_eve_cd.uchar = latest_du->byte1.bf.id14;
event_count ++;
}
if (g_latest_du.byte1.bf.id15 != latest_du->byte1.bf.id15) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 15;
events[event_count].eve_eve_cd.uchar = latest_du->byte1.bf.id15;
event_count ++;
}
if (g_latest_du.byte2.bf.id16 != latest_du->byte2.bf.id16) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 16;
events[event_count].eve_eve_cd.uchar = latest_du->byte2.bf.id16;
event_count ++;
}
if (g_latest_du.byte2.bf.id17 != latest_du->byte2.bf.id17) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 17;
events[event_count].eve_eve_cd.uchar = latest_du->byte2.bf.id17;
event_count ++;
}
if (g_latest_du.byte2.bf.id18 != latest_du->byte2.bf.id18) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 18;
events[event_count].eve_eve_cd.uchar = latest_du->byte2.bf.id18;
event_count ++;
}
if (g_latest_du.byte2.bf.id19 != latest_du->byte2.bf.id19) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 19;
events[event_count].eve_eve_cd.uchar = latest_du->byte2.bf.id19;
event_count ++;
}
if (g_latest_du.byte2.bf.id20 != latest_du->byte2.bf.id20) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 20;
events[event_count].eve_eve_cd.uchar = latest_du->byte2.bf.id20;
event_count ++;
}
if (g_latest_du.byte2.bf.id21 != latest_du->byte2.bf.id21) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 21;
events[event_count].eve_eve_cd.uchar = latest_du->byte2.bf.id21;
event_count ++;
}
if (g_latest_du.byte2.bf.id22 != latest_du->byte2.bf.id22) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 22;
events[event_count].eve_eve_cd.uchar = latest_du->byte2.bf.id22;
event_count ++;
}
if (g_latest_du.byte2.bf.id23 != latest_du->byte2.bf.id23) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 23;
events[event_count].eve_eve_cd.uchar = latest_du->byte2.bf.id23;
event_count ++;
}
if (g_latest_du.byte3.bf.id24 != latest_du->byte3.bf.id24) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 24;
events[event_count].eve_eve_cd.uchar = latest_du->byte3.bf.id24;
event_count ++;
}
if (g_latest_du.byte3.bf.id25 != latest_du->byte3.bf.id25) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 25;
events[event_count].eve_eve_cd.uchar = latest_du->byte3.bf.id25;
event_count ++;
}
if (g_latest_du.byte3.bf.id26 != latest_du->byte3.bf.id26) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 26;
events[event_count].eve_eve_cd.uchar = latest_du->byte3.bf.id26;
event_count ++;
}
if (g_latest_du.byte3.bf.id27 != latest_du->byte3.bf.id27) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 27;
events[event_count].eve_eve_cd.uchar = latest_du->byte3.bf.id27;
event_count ++;
}
if (g_latest_du.byte3.bf.id28 != latest_du->byte3.bf.id28) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 28;
events[event_count].eve_eve_cd.uchar = latest_du->byte3.bf.id28;
event_count ++;
}
if (g_latest_du.byte3.bf.id29 != latest_du->byte3.bf.id29) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 29;
events[event_count].eve_eve_cd.uchar = latest_du->byte3.bf.id29;
event_count ++;
}
if (g_latest_du.byte3.bf.id30 != latest_du->byte3.bf.id30) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 30;
events[event_count].eve_eve_cd.uchar = latest_du->byte3.bf.id30;
event_count ++;
}
if (g_latest_du.byte3.bf.id31 != latest_du->byte3.bf.id31) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 31;
events[event_count].eve_eve_cd.uchar = latest_du->byte3.bf.id31;
event_count ++;
}
if (g_latest_du.byte4.bf.id32 != latest_du->byte4.bf.id32) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 32;
events[event_count].eve_eve_cd.uchar = latest_du->byte4.bf.id32;
event_count ++;
}
if (g_latest_du.byte4.bf.id33 != latest_du->byte4.bf.id33) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 33;
events[event_count].eve_eve_cd.uchar = latest_du->byte4.bf.id33;
event_count ++;
}
if (g_latest_du.byte4.bf.id34 != latest_du->byte4.bf.id34) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 34;
events[event_count].eve_eve_cd.uchar = latest_du->byte4.bf.id34;
event_count ++;
}
memcpy(&g_latest_du, latest_du, sizeof(DU_t));
} else if (latest_du->func_cd.uchar == 0x43) { //0x43==C; clear data
//C
if (g_latest_du.byte0.bf.id00 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 0;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte0.bf.id01 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 1;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte0.bf.id02 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 2;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte0.bf.id03 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 3;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte0.bf.id04 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 4;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte0.bf.id05 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 5;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte0.bf.id06 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 6;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte0.bf.id07 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 7;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte1.bf.id08 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 8;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte1.bf.id09 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 9;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte1.bf.id10 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 10;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte1.bf.id11 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 11;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte1.bf.id12 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 12;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte1.bf.id13 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 13;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte1.bf.id14 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 14;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte1.bf.id15 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 15;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte2.bf.id16 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 16;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte2.bf.id17 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 17;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte2.bf.id18 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 18;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte2.bf.id19 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 19;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte2.bf.id20 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 20;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte2.bf.id21 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 21;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte2.bf.id22 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 22;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte2.bf.id23 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 23;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte3.bf.id24 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 24;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte3.bf.id25 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 25;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte3.bf.id26 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 26;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte3.bf.id27 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 27;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte3.bf.id28 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 28;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte3.bf.id29 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 29;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte3.bf.id30 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 30;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte3.bf.id31 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 31;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte4.bf.id32 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 32;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte4.bf.id33 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 33;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
if (g_latest_du.byte4.bf.id34 == FLG_ON) {
events[event_count].eve_datetime.ullint = now_ms;
events[event_count].eve_type_num.uchar = 34;
events[event_count].eve_eve_cd.uchar = FLG_CLEAR;
event_count ++;
}
}
if (event_count > 0) {
insert_event(events,event_count);
}
} 
else 
{
usleep(50000);
}
}
return TRUE;
}

要从 C 程序中的串行端口读取,您必须使用 操作系统调用select()。调用时,您将"挂起">,直到超时或某些数据准备好读取。

请参阅 POSIX 操作系统串行编程指南

  1. 查看变量和参数类型。ctl_auto_duint *(文件描述符(作为参数, 但是您正在传递它FILE *(文件指针(。

    • 解决此问题的最佳(即"正确"(方法可能是更改

      FILE *dental_unit_data;         //new
      ︙
      dental_unit_data = fopen("/dev/ttymxc3", "r"); 
      ctl_auto_du(dental_unit_data); //reads the data from the dental_uni_data 
      

      int   dental_unit_data;         //new
      ︙
      dental_unit_data = open("/dev/ttymxc3", O_RDONLY); 
      ctl_auto_du(&dental_unit_data); //reads the data from the dental_uni_data 
      
    • 或者,您可以将dental_unit_data声明为FILE *并保留fopen,并将呼叫更改为ctl_auto_du

      ctl_auto_du(&fileno(dental_unit_data)); //reads the data … 
      

      虽然我不确定这是否保证是便携式的。

  2. 虽然ctl_auto_du功能很长, 看起来所有真正的I/O工作都发生在recv_du, 而你没有向我们展示。 因此,如果问题存在,我们将无法找到它。

相关内容

  • 没有找到相关文章

最新更新