原创 串口扩展芯片VK3214使用总结

2012-5-9 12:40 5725 10 12 分类: MCU/ 嵌入式

最近一个项目需要用到3个串口,但是用的MCU只有2个串口,选择多串口的单片机成本太高,最后打算用串口扩展芯片VK3214扩展2个串口。

VK3214可以用单片机的一个串口扩展出4个子串口,每个子串口都可以单独设置波特率。

脚位图如下:

 

MRX,MTX分别接单片机一个串口的TX,RX。RXn,TXn 为扩展的4个子串口。

每个子串口有16字节的发送FIFO,16字节的接收FIFO。当发送FIFO触发点中断使能时,发送FIFO中的数据小于设定的触发点时产生相应的中断。当接收FIFO触发点中断使能时,接收FIFO中的数据大于设定的触发点时产生相应的中断。

中断脚IRQ低电平有效,注意不是下降沿有效。IRQ接单片机的中断脚,中断脚接单片机的外部中断脚INT,INT要设置为低电平有效。因为是低电平有效,在进入中断程序后,要禁止外部中断,中断处理完后再开外部中断。

例如当接收FIFO中断使能,触发点设置为1,那么在接收FIFO中的数据大于1时,IRQ变低,产生中断,此时进入中断程序,在中断程序中要读完FIFO中的全部数据,接收FIFO的数据变为0时,IRQ才变为高。如果没读完FIFO退出中断,IRQ仍会为低,退出中断后,马上又进入中断程序,导致其它程序不能执行。

初始化VK3214时,要初始化完后再使能单片机的外部中断,否则会因为IRQ一直为低,导致程序一直运行外部中断程序,其它程序无法运行。

初始化程序如下:

void Vk3214_Init(void){

 

        uchar i;

       FREEDOG;

       VK3214_RST=1;

       delay(10);

       VK3214_RST=0;

       delay(10);

       VK3214_RST=1;

       delay(10);

      

      

       write_reg(1,SCTLR,0x38); //串口1波特率设置为9600,使能串口1

      

       write_reg(2,SCTLR,0x38);//串口2ㄌ芈噬柚梦?600,使能串口1

       //write_reg(3,SCTLR,0x30);//禁止串口3

       //write_reg(4,SCTLR,0x30);//禁止串口4

 

       //write_reg(0,SCONR,0x00);

       //write_reg(1,SCONR,0x00);

       //write_reg(2,SCONR,0x00);

       //write_reg(3,SCONR,0x00);

 

       //write_reg(0,SFWCR,0x00);

       //write_reg(1,SFWCR,0x00);

       //write_reg(2,SFWCR,0x00);

       //write_reg(3,SFWCR,0x00);

 

       write_reg(1,SFOCR,0xcf);//接收FIFO触点控制1BYTE

       //i = read_reg(1, SFOCR);

       //SENDCOM1(&i,1);

       write_reg(2,SFOCR,0xcf);

       //write_reg(2,SFOCR,0xcc);

 

       write_reg(1,SIER,0x01);//使能接收FIFO触点中断,禁止发送FIFO触点中断

       write_reg(2,SIER,0x01);

       //write_reg(2,SIER,0x00);

       //write_reg(3,SIER,0x00);

      

       //write_reg(0,SIFR,0x00);

       //write_reg(1,SIFR,0x00);

       //write_reg(2,SIFR,0x00);

       //write_reg(3,SIFR,0x00);

 

       write_reg(1,GIR,0X30);//使能串口1, 2中断

      

       while(read_reg(1,SFSR))//读完串口1,2接收FIFO中的数据

              read_reg(1,SFDR);

       while(read_reg(2,SFSR))

              read_reg(2,SFDR);

       write_reg(1,GUCR,0X10);//主串口波特率设为38400

      

       AUXR=0x14;///S2使用独立波特率发生器,S2波特率不加倍BRTX12设为1

       BRT=0xf7;//0xee;//0xf7;//设置波特率38400

       delay(10);

       }

为保证及时接收到扩展串口的数据,接收FIFO触发点中断设置为1,即接收到1个字节就产生中断,发送因为是单片机控制,不用设置触发点中断。

//********************************************************************

void uart_sendByte(unsigned char dat)

{

       S2BUF=dat;

       while(!(S2CON & 0x02));                            //waite for data to transmit completely

           S2CON &= 0xFD;

}

//通过串口发送1个字节的数据,dat为发送的数据

//**************************************************************************

 

//***************************************************************************

unsigned char uart_recByte(void)

{

       unsigned char rec=0;

       while(!(S2CON & 0x01));                          //waite to recieve data in SBUF0

       rec=S2BUF;

           S2CON &= 0xFE;

       return rec;

}

//接收一个字节的数据,函数返回读取到的数据

//***************************************************************************

 

//***************************************************************************

unsigned char read_reg(unsigned char port,unsigned char reg)

{

       uchar i;

       EX1 = 0; //此处关外部1中断,避免在读写寄存器时,串口芯片接收到数据引起外部中断,在外部中断调用相同的寄存器会导致死机

       uart_sendByte(((port-1)<<4)+reg);

       i =  uart_recByte();

       EX1 = 1;

       return i;

}

//读取寄存器的值,port为子串口的路数,reg为寄存器的地址,返回值是寄存器的值

//***************************************************************************

 

//****************************************************************************

void write_reg(unsigned char port,unsigned char reg,unsigned char dat)

{

       EX1 = 0;

       uart_sendByte(0x80+((port-1)<<4)+reg);

       uart_sendByte(dat);

       EX1 = 1;

}

从上面的函数可以看出,单片机的串口控制VK3214的串口,读写都是先发送VK3214的寄存器地址,然后再读写数据,所以如果单片机的串口和扩展的子串口的波特率设置成一样,会导致子串口接收FIFO溢出,再考虑到用单片机的一个串口控制2-4个子串口,所以单片机的串口波特率一定要是子串口波特率的倍数,我现在扩展2个串口,子串口的波特率为9600,所以我把单片机串口的波特率设置为38400,是子串口的4倍。倍数要考虑好,太慢会导致接收FIFO溢出,太快会导致发送FIFO的数据还没发出去,有送进来新的数据,发送FIFO溢出。

VK3214复位后根据外接的晶振,主,子串口都有默认的波特率,单片机上电后先把波特率设为和VK3214主串口波特率一样,初始化VK3214完成后,在改变VK3214的主串口波特率和单片机串口的波特率。见初始化程序的最后部分。

 

接下来关键的部分是外部中断程序的处理。程序如下:

void Int1Init(void) interrupt 2

{

       uchar x,i,j,z;

       EX1 = 0;

       uart_sendByte(GIR);

       i=uart_recByte();

       FREEDOG;

       if(i&0x01)

       {

              uart_sendByte((0<<4)+SSR);

              z=uart_recByte();

              z&=0x01;

              while(z==0)

              {

                    

                            uart_sendByte((0<<4)+SFDR);

                            com2rev[com2revidx++] = uart_recByte();

                            FREEDOG;

                            if(com2revidx>=COM2_MAX)com2revidx=0;

                            uart_sendByte((0<<4)+SSR);

                            z=uart_recByte();

                            z&=0x01;

                    

              }

       }

       if(i&0x02)

              {

                     uart_sendByte((1<<4)+SSR);

              z=uart_recByte();

              z&=0x01;

              while(z==0)

              {

                    

                            uart_sendByte((1<<4)+SFDR);

                            com3rev[com3revidx++] = uart_recByte();

                            FREEDOG;

                            if(com3revidx>=COM3_MAX)com3revidx=0;

                            uart_sendByte((1<<4)+SSR);

                            z=uart_recByte();

                            z&=0x01;

              }

              }

EX1 = 1;

       }

进入中断后先判断是哪个子串口产生的中断,如果是子串口1产生的接收中断,那么读子串口1的寄存器SSR,看接收FIFO是否为空,不为空就一直读子串口1的接收FIFO,直到FIFO为空。中断程序中一定要把接收FIFO的数据读完,因为我设置的接收FIFO触发点数据为1。如果不读完退出中断,IRQ仍然会为低,还会继续进入中断程序。读完后,IRQ才变为高。 

文章评论2条评论)

登录后参与讨论

用户377235 2015-7-25 11:24

功能最完善、使用最简单的串口扩展,多串口芯片WK系列; v 每个子串口收发独立的FIFO达到256字节; v 主接口灵活选择串口,SPI,I2C,8位总线; v 封装灵活选择SOP,SSOP,QFN,QFP; v 增加超时中断等功能。 v WK2114 UART一扩四; v WK2124/2 SPI一扩四/二; v WK2142 I2C一扩二; v WK2166 全接口一扩四。 v VK32xx,VK33xx系列。 应用领域: ü 多串口服务器/多串口卡 ü 工业/自动化现场RS-485控制 ü 通过CDMA/GPRS MODEM的无线数据传输 ü 车载信息平台/车载GPS定位系统 ü 远传自动抄表(AMR)系统 ü POS/税控POS/金融机具 ü DSP/嵌入式系统 维肯华南片区总代理。 0755-83417835 -802 彭.S Q 463280305 免费申请样品 和技术支持服务

用户377235 2015-6-11 14:15

vk3214我也用过,还不错性能也很稳定。我最近用了一款更好用的wk2114的串口扩展芯片,感觉更好用,FIFO是256字节,有超时中断。可以去成都为开微电子有限公司的官网申请样片。www.wkmic.com
相关推荐阅读
用户1035191 2012-05-18 16:36
根据年月日计算星期
在门禁系统中要用到星期,但是在设置时间的时候,一般只设置年月日时分秒,不会去设置星期,那么如何根据年月日来得到星期?有一个公式: (年+年/4+年/400-年/100-年基数+月基数+日)%7...
用户1035191 2011-10-12 17:54
STM32串口发送时序图分析
下面是STM32使用手册上的串口发送时序图:1、 使能串口发送TE,此时USART_DR为空,此时应查询TXE是否置1,TXE置1,TX脚先发送一个空闲帧,把F1帧写入USART_DR,TXE被清零。...
用户1035191 2011-09-30 14:52
STM32的RTC实现日历功能程序
STM32的RTC只有一个32位的计数器用来计时,没有寄存器来存年月日时分秒等。通过设置可以让这个计数器1秒加1,从0-0XFFFFFFFF大概可以计时136年。程序要设置一个时间起点表示0,一般设...
用户1035191 2011-09-14 17:30
C语言计算时间差
以前曾写过一篇文章C51计算时间差,采用的算法是网上查到的,虽然测试没有问题,但是感觉那种算法不便于理解。最近重新考虑了一种算法。 用2个BCD码数组存储进场时间和出场时间: unsigned ch...
用户1035191 2011-08-24 17:06
C51扩展外部RAM释放P2口
51单片机经常要使用一些外部器件,有些器件内部有寄存器,一般都把这些寄存器当做外部RAM读写。以IC卡读卡芯片RC500为例,这个芯片有D0-D7共8个数据线,接在51的P0口,D0-D7既做>...
我要评论
2
10
关闭 站长推荐上一条 /2 下一条