精华内容
下载资源
问答
  • 用于1串口扩展4路232串口,SPI接口,每路带有中断和RST,适用于串口服务器等领域
  • 基于RK3399 串口扩展4个串口的驱动代码。
  • RK3399-Wk2114串口扩展驱动,串口扩展芯片wk2124,C,C++源码.rar
  • RK3399-Wk2114串口扩展驱动,串口扩展芯片wk2124,C,C++源码.zip
  • 本驱动程序基于wk2166串口扩展芯片,实现了spi转串口的linux驱动程序的设计。本驱动源代码在为开微电子的网站也能找到源码。。
  • 串口扩展芯片,支持UART/IIC/SPI/并行总线接口,可扩展4路串口。硬件简单,电源种类单一。串口设计简单易操作。
  • 串口扩展芯片

    千次阅读 2020-06-24 14:50:51
    串口扩展芯片 WK2124 实现SPI桥接/扩展4个增强功能串口(UART)功能。扩展的子通道具备以下功能特点: 每个子通道UART的波特率、字长、校验格式可以独立设置,最高可以提供2Mbps的通道速率; 每个子通道可以独立...

    串口扩展芯片

    WK2124

    实现SPI桥接/扩展4个增强功能串口(UART)功能。扩展的子通道具备以下功能特点:

    1. 每个子通道UART的波特率、字长、校验格式可以独立设置,最高可以提供2Mbps的通道速率;
    2. 每个子通道可以独立设置工作在IrDA红外通信;
    3. 每个子通道具备收/发独立的256 BYTE FIFO,FIFO的中断可按用户需求进行编程触发点;

    封装:SSOP20
    工作电压:2.5~5.0V
    具备自动休眠/唤醒功能

    原理框图

    在这里插入图片描述

    封装引脚图

    在这里插入图片描述

    与控制器接口

    在这里插入图片描述

    1. SPI总线:WK2124通过SPI和MCU进行数据通信。SPI会传输命令字节和数据字节。
    2. 中断:WK2124的IRQ连接到MCU的外部中断输入引脚。这个连接非必须,未连接时只能通过查询的编程方式实现对子串口的数据收发,效率较低;
    3. 复位控制:低电平有效,时间长度为10ms。复位以后,所有寄存器值恢复到默认值,SPI总线上的命令解析同时复位;
    4. 时钟电路:采用无源晶振,晶振大小和子串口波特率相关;晶振必须并联的匹配电阻是1M欧姆;
    展开全文
  • 对spi转串口驱动wk2124驱动程序的优化@SPI转串口驱动 ...以下是芯片的封装引脚图1个芯片可以扩展4路串口。 2. 现对驱动程序作出以下修改 注:本人移植到的内核是3.2版本会删除设备树部分代码 把驱动注册函数从probe函

    对spi转串口驱动wk2124驱动程序的优化@SPI转串口驱动

    一. WK2XXXX原厂驱动程序下载

    官网: http://www.wkmic.com/

    在这里插入图片描述
    进入到为开官网点击技术支持
    在这里插入图片描述
    然后再点击驱动参考

    在这里插入图片描述
    下载驱动程序,可以得到源码和头文件以及一个Makefile 文件还有一份移植文档, 本人借鉴的是该公司2019年10月份的驱动程序。

    以下是芯片的封装引脚图1个芯片可以扩展4路串口。
    在这里插入图片描述

    2. 现对驱动程序作出以下修改

    注:本人移植到的内核是3.2版本会删除设备树部分代码

    在这里插入图片描述
    把驱动注册函数从probe函数移到模块入口函数更为合理

    在这里插入图片描述
    要使用控制台功能需要在UBOOT中修改启动环境变量比如: console=ttyWK0,115200n8

    在这里插入图片描述

    本人扩展的是8路串口所以使用2片该芯片所以,驱动程序还作出其他的修改,具体可以比较原厂源码对比修改,具体源码到我的文件中下载

    在这里插入图片描述

    展开全文
  • 因为项目用到了wk2124芯片来进行串口扩展,网上找了好多资料没有现成的,根据商家提供的demo,它是基于103写的,所以根据自己板子的实际情况进行了改写,并且学习一下里面的主要函数及我对函数的理解 原理图 ...

    目录

    引言

    一. SPI通信配置

    1.GPIO初始化设置

    2.SPI参数配置

    3.读写函数

    4.速度设置

    二、WK2124逻辑代码编写

    1.片选初始化

    2. 写寄存器函数

    3. 读寄存器函数

    4. 写FIFO函数

    5.读FIFO函数

    6. WK2124初始化函数

    7.wk2124关闭及复位函数

    8. 波特率设置函数

    8.发送字节函数

    9. 接收数据函数

    三、测试


    引言

    因为项目用到了wk2124芯片来进行串口扩展,网上找了好多资料没有现成的,根据商家提供的demo,它是基于103写的,所以根据自己板子的实际情况进行了改写,并且学习一下里面的主要函数及我对函数的理解

    原理图

     用到5个引脚,片选CS、时钟SCK、MOSI、MISO和中断IRQ,因为RST设置的是板子连电后电容充电,所以会自动复位,不用这个引脚。

    一. SPI通信配置

    1.GPIO初始化设置

      GPIO_InitTypeDef GPIO_InitStructure;
    
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB时钟
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//使能SPI2时钟,在APB1时钟里面
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
      //PB13-15分别复用为SCK,MISO,MOSI
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
      GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
    
      GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
    

    2.SPI参数配置

     

     

     

    因为发送接收是同时进行,所以选择全双工,SPI设置为主模式 ,大小为8bit,时钟默认拉低,第二个时钟沿开始捕捉,数据格式SPI_FirstBit(选择是MSB还是LSB),选择MSB方式,举个例子假设用16bit,就是[15,0]这样,如果是LSB就是[0,15]这样。

    
    	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //SPI设置为双线双向全双工
    	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		//设置为主SPI
    	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;		//SPI发送接收8位帧结构
    	SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;		//时钟悬空低
    	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;	//数据捕获于第二个时钟沿
    	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		//NSS信号由软件(使用SSI位)管理
    	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;	//定义波特率预分频的值:波特率预分频值为256
    	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	//数据传输从MSB位开始
    	SPI_InitStructure.SPI_CRCPolynomial = 7;	//CRC值计算的多项式
    	SPI_Init(SPI2, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
     
    	SPI_Cmd(SPI2, ENABLE); //使能SPI外设
    	SPI2_ReadWriteByte(0xff);//启动传输

    3.读写函数

    u8 SPI2_ReadWriteByte(u8 TxData)
    {		
    	u8 retry=0;				 	
    	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //发送缓存空标志位
    		{
    		retry++;
    		if(retry>200)return 0;
    		}			  
    	SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据
    	retry=0;
    
    	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)//接受缓存非空标志位
    		{
    		retry++;
    		if(retry>200)return 0;
    		}	  						    
    	return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据					    
    }

    读写函数中,用SPI_I2S_GetFlagStatus不断去获取TXE和RXNE的状态,如果是非空就继续,如果为空就调用Send和Rece函数去发送接收数据,当retry标志连续超过200次,就返回0,发送/接收失败。

    4.速度设置

    void SPI2_SetSpeed(u8 SpeedSet)
    {
    	SPI_InitStructure.SPI_BaudRatePrescaler = SpeedSet ;
        SPI_Init(SPI2, &SPI_InitStructure);
    	SPI_Cmd(SPI2,ENABLE);
    } 

     

    二、WK2124逻辑代码编写

    引脚对应关系

    CS    PB12
    SCK   PB13
    MOSI  PB15
    MISO  PB14
    IRQ   PB1

     

    1.片选初始化

    void SPI_CS_Init(void)
    {
     GPIO_InitTypeDef  GPIO_InitStructure;
     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);		 //使能PB端口时钟
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;	//PB12端口配置
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//输出
     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出	
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;		 //IO口速度为100MHz
     GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIOB12
     GPIO_SetBits(GPIOB,GPIO_Pin_12);						 //PB12 输出高	
    }

     

    2. 写寄存器函数

    void WK2124WriteReg(unsigned char port,unsigned char reg,unsigned char dat)
    {	 
    	 SPI_CS_L();//片选使能
    	 SPI2_ReadWriteByte(((port-1)<<4)+reg); //写控制字节
    	 SPI2_ReadWriteByte(dat); //写数据
    	 SPI_CS_H();//片选无效
    }

    首先把片选信号拉低,然后写入控制命令,再写入数据,写完之后再拉高片选,对于其中的控制字节((port-1)<<4)+reg可以根据数据手册得知,port:为子串口的端口号(C0\C1),reg是目标寄存器,dat是数据。

    6,7位为默认为0,0,C1,C0为串口通道,可选值为00,01,10,11分别表示4个串口,默认设置为00,通过传入参数port(port设置的是1,2,3,4,但是因为从0开始,所以要port-1)来进行改变,然后左移4位变成00 0000,然后加上初始的默认值0000 0000,最后加上要写入的寄存器,所以其实是0x00+(port-1)<<4)+reg,然后将这个cmd传入spi读写函数进行读写。

     

    3. 读寄存器函数

    unsigned char WK2124ReadReg(unsigned char port,unsigned char reg)
    {	
    	unsigned char rec_data; 
    	SPI_CS_L();	//片选使能
    	SPI2_ReadWriteByte(0x40+((port-1)<<4)+reg);//写控制字节
    	rec_data=SPI2_ReadWriteByte(0);//接收返回的数据
    	SPI_CS_H();	//片选无效	
    	return rec_data;
    }

    4. 写FIFO函数

    void WK2124WriteFifo(unsigned char port,unsigned char *wbuf,unsigned int len)
    {	 unsigned char n;
    	 SPI_CS_L(); // 片选有效
    	 SPI2_ReadWriteByte(0x80+((port-1)<<4)); //写FIFO控制指令
    	  for(n=0;n<len;n++)
    	  {
    	     SPI2_ReadWriteByte(*(wbuf+n));
    		} 
    	 SPI_CS_H();	//片选无效
    
    }

      port:为子串口的端口号(C0\C1), *wbuf:写入数据部分, len:  写入数据长度。

    大部分和读写寄存器相同,主要控制字节不同,其次可以一次写入多个数据。

    控制字节的变化主要是初始SPI的CMD为1000 0000,也就是0x80,其他一样。

     

    5.读FIFO函数

    void WK2124WriteFifo(unsigned char port,unsigned char *wbuf,unsigned int len)
    {	 unsigned char n;
    	 SPI_CS_L(); // 片选有效
    	 SPI2_ReadWriteByte(0x80+((port-1)<<4)); //写FIFO控制指令
    	  for(n=0;n<len;n++)
    	  {
    	     SPI2_ReadWriteByte(*(wbuf+n));
    		} 
    	 SPI_CS_H();	//片选无效
    
    }

     

    6. WK2124初始化函数

    首先使能子串口时钟

    
        unsigned char gena,grst,gier,sier,scr;
    	//使能子串口时钟
        gena=WK2124ReadReg(WK2124_GPORT,WK2124_GENA); 
    	switch (port)
        {
              case 1://使能子串口1的时钟
                  gena|=WK2124_UT1EN;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GENA,gena);
                  break;
    		  case 2://使能子串口2的时钟
                  gena|=WK2124_UT2EN;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GENA,gena);
                  break;
    		   case 3://使能子串口3的时钟
                  gena|=WK2124_UT3EN;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GENA,gena);
                  break;
    		   case 4://使能子串口4的时钟
                  gena|=WK2124_UT4EN;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GENA,gena);
                  break;
    	 }	
    	

    在头文件中对GENA全局寄存器进行了宏定义:

    #define 	WK2124_UT4EN	0x08
    #define 	WK2124_UT3EN	0x04
    #define 	WK2124_UT2EN	0x02
    #define 	WK2124_UT1EN	0x01

    根据数据手册说明,低位的0,1,2,3位置1,就使能哪个子串口,如ut2使能就是0000 0010,也就是0x02。

    接下来进行串口复位

    //软件复位子串口
    	grst=WK2124ReadReg(WK2124_GPORT,WK2124_GRST); 
    	switch (port)
        {
              case 1://软件复位子串口1
                  grst|=WK2124_UT1RST;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GRST,grst);
                  break;
    		  case 2://软件复位子串口2
                  grst|=WK2124_UT2RST;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GRST,grst);
                  break;
    		   case 3://软件复位子串口3
                  grst|=WK2124_UT3RST;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GRST,grst);
                  break;
    		   case 4://软件复位子串口4
                 grst|=WK2124_UT4RST;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GRST,grst);
                  break;
    	 }	
     

    与上面一样,第四位哪个置1,表示哪个子串口进行复位。 

    接下来使能串口中断

     //使能子串口中断,包括子串口总中断和子串口内部的接收中断,和设置中断触点
    	gier=WK2124ReadReg(WK2124_GPORT,WK2124_GIER); 
    	switch (port)
        {
              case 1://子串口1中断使能
                  gier|=WK2124_UT1IE;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GIER,gier);
                  break;
    		  case 2://子串口2中断使能
                  gier|=WK2124_UT2IE;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GIER,gier);
                  break;
    		   case 3://子串口3中断使能
                  gier|=WK2124_UT3IE;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GIER,gier);
                  break;
    		   case 4://子串口4中断使能
                  gier|=WK2124_UT4IE;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GIER,gier);
                  break;
    	 }	 
    	

    寄存器设置与上面一样。

         //使能子串口接收触点中断和超时中断
    	 sier=WK2124ReadReg(port,WK2124_SIER); 
    	 sier |= WK2124_RFTRIG_IEN;
    	 WK2124WriteReg(port,WK2124_SIER,sier);
    	 // 初始化FIFO和设置固定中断触点
    	 WK2124WriteReg(port,WK2124_FCR,0XFF);
    	 //设置任意中断触点,如果下面的设置有效,那么上面FCR寄存器中断的固定中断触点将失效
    	 WK2124WriteReg(port,WK2124_SPAGE,1);//切换到page1
    	 WK2124WriteReg(port,WK2124_RFTL,0X08);//设置接收触点8个字节
    	 WK2124WriteReg(port,WK2124_TFTL,0X10);//设置发送触点为16个字节
    	 WK2124WriteReg(port,WK2124_SPAGE,0);//切换到page0 
    	 //使能子串口的发送和接收使能
    	 scr=WK2124ReadReg(port,WK2124_SCR); 
    	 scr|=WK2124_TXEN|WK2124_RXEN;
    	 WK2124WriteReg(port,WK2124_SCR,scr);
    

     

    剩下的这些触点,页面设置,使能都一样,根据数据手册进行设置即可。

     

    7.wk2124关闭及复位函数

    void WK2124Close(unsigned char port)
    {
        unsigned char gena,grst;
    	//复位子串口
    	grst=WK2124ReadReg(WK2124_GPORT,WK2124_GRST); 
    	switch (port)
        {
              case 1://软件复位子串口1
                  grst|=WK2124_UT1RST;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GRST,grst);
                  break;
    		  case 2://软件复位子串口2
                  grst|=WK2124_UT2RST;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GRST,grst);
                  break;
    		   case 3://软件复位子串口3
                  grst|=WK2124_UT3RST;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GRST,grst);
                  break;
    		   case 4://软件复位子串口4
                  grst|=WK2124_UT4RST;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GRST,grst);
                  break;
    	 }	
    	//关闭子串口时钟
        gena=WK2124ReadReg(WK2124_GPORT,WK2124_GENA); 
    	switch (port)
        {
              case 1://使能子串口1的时钟
                  gena&=~WK2124_UT1EN;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GENA,gena);
                  break;
    		  case 2://使能子串口2的时钟
                  gena&=~WK2124_UT2EN;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GENA,gena);
                  break;
    		   case 3://使能子串口3的时钟
                  gena&=~WK2124_UT3EN;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GENA,gena);
                  break;
    		   case 4://使能子串口4的时钟
                  gena&=~WK2124_UT4EN;
    		      WK2124WriteReg(WK2124_GPORT,WK2124_GENA,gena);
                  break;
    	 }	
    }

    先对GRST寄存器进行操作使其复位,然后利用~运算符关闭串口时钟,同时可以减少参数量。

     

    8. 波特率设置函数

    void WK2124SetBaud(unsigned char port,int baud)
    {  
    	unsigned char baud1,baud0,pres,scr;
    	//如下波特率相应的寄存器值,是在外部时钟为11.0592的情况下计算所得,如果使用其他晶振,需要重新计算
    	switch (baud) 
    	{
          case 600:
    			baud1=0x4;
    			baud0=0x7f;
    			pres=0;
          break;
          case 1200:
    			baud1=0x2;
    			baud0=0x3F;
    			pres=0;
    			break;
          case 2400:
    			baud1=0x1;
    			baud0=0x1f;
    			pres=0;
    			break;
          case 4800:
    			baud1=0x00;
    			baud0=0x8f;
    			pres=0;
    			break;
          case 9600:
    			baud1=0x00;
    			baud0=0x47;
    			pres=0;
    			break;
          case 19200:
    			baud1=0x00;
    			baud0=0x23;
    			pres=0;
    			break;
          case 38400:
    			baud1=0x00;
    			baud0=0x11;
    			pres=0;
    			break;
    			
          case 76800:
    			baud1=0x00;
    			baud0=0x08;
    			pres=0;
    			break; 
           
          case 1800:
    			baud1=0x01;
    			baud0=0x7f;
    			pres=0;
    			break;
          case 3600:
    			baud1=0x00;
    			baud0=0xbf;
    			pres=0;
    			break;
          case 7200:
    			baud1=0x00;
    			baud0=0x5f;
    			pres=0;
    			break;
          case 14400:
    			baud1=0x00;
    			baud0=0x2f;
    			pres=0;
    			break;
          case 28800:
    			baud1=0x00;
    			baud0=0x17;
    			pres=0;
    			break;
          case 57600:
    			baud1=0x00;
    			baud0=0x0b;
    			pres=0;
          break;
          case 115200:
    			baud1=0x00;
    			baud0=0x05;
    			pres=0;
    			break;
          case 230400:
    			baud1=0x00;
    			baud0=0x02;
    			pres=0;
    			break;
          default:
    			baud1=0x00;
    			baud0=0x00;
    			pres=0;
        }
    	
    	//关掉子串口收发使能
    	scr=WK2124ReadReg(port,WK2124_SCR); 
    	WK2124WriteReg(port,WK2124_SCR,0);
    	//设置波特率相关寄存器
    	WK2124WriteReg(port,WK2124_SPAGE,1);//切换到page1
    	WK2124WriteReg(port,WK2124_BAUD1,baud1);
    	WK2124WriteReg(port,WK2124_BAUD0,baud0);
    	WK2124WriteReg(port,WK2124_PRES,pres);
    	WK2124WriteReg(port,WK2124_SPAGE,0);//切换到page0 
    	//使能子串口收发使能
    	WK2124WriteReg(port,WK2124_SCR,scr);
    	
    	
    }

    计算公式:

    Reg整数部分减一并换算成16进制写入{BAUD1,BAUA0};如果还有小数部分,则小数部分*16,然后4舍5入后取整写入PRES。如果没有小数部分,只需把整数部分写入 { BAUD1,BAUA0},PRES写入0即可。

    例子:

    根据具体晶振去设置即可。

     

    8.发送字节函数

    unsigned int WK2124SendBuf(unsigned char port,unsigned char *sendbuf,unsigned int len)
    {
    	 unsigned int ret,tfcnt,sendlen;
    	 unsigned char  fsr;
    	  
    	 fsr=WK2124ReadReg(port,WK2124_FSR);
    	 if(~fsr&WK2124_TFULL )//子串口发送FIFO未满
    	 {
    
    	     tfcnt=WK2124ReadReg(port,WK2124_TFCNT);//读子串口发送fifo中数据个数
    		 sendlen=256-tfcnt;//FIFO能写入的最多字节数
    		 
    		 if(sendlen<len)
    		 {
    			ret=sendlen; 
    			WK2124WriteFifo(port,sendbuf,sendlen);
    		 }
    		 else
    		 {
    			 WK2124WriteFifo(port,sendbuf,len);
    			 ret=len;
    		 }
    	  }
    	 
    	 return ret;
    }

     

    9. 接收数据函数

    unsigned int WK2124GetBuf(unsigned char port,unsigned char *getbuf)
    {
    	unsigned int ret=0,rfcnt;
    	unsigned char fsr;
    	fsr=WK2124ReadReg(port,WK2124_FSR);
    	if(fsr&WK2124_RDAT )//子串口发送FIFO未满
    	  {
    	     rfcnt=WK2124ReadReg(port,WK2124_RFCNT);//读子串口发送fifo中数据个数
    		 if(rfcnt==0)//当RFCNT寄存器为0的时候,有两种情况,可能是256或者是0,这个时候通过FSR来判断,如果FSR显示接收FIFO不为空,就为256个字节
    		 {rfcnt=256;}
    		 WK2124ReadFifo(port,getbuf,rfcnt);
    		 ret=rfcnt;
    	   }
    	 return ret;	
    }

          最后有一点,UART端口输出为TTL电平,如果需要232或485电平的,需要加相应的电平转换芯片。

          踩坑记录:如果读写寄存器是0的情况下,将芯片的子串口短接,进行自收发测试,如果成功就说明子串口到外接的通信有问题,如果失败就说明2124和主控芯片之间的通信有问题,检查一下通信过程。

    我有一步是SPI配置的时候预分频给了256,太大了导致通信失败,将它改为8分频。

    要看一下SPI的CPOL,CPHA,应该在LOW状态捕捉第一个边沿,参考数据手册,否则的话也是收发有问题。

    不同频率的晶振记得根据公式改写波特率,否则通信有问题。

    还有好多坑,想不起来了。

    三、测试

    配置好后4个串口测试:

    单个字符/数

     

    字符写入测试:

    进行两次写入观察,写入的一致。

     

    FIFO串口4与STM32串口1通信测试:

     

    数据缓存区测试 :

     

     

    展开全文
  • 此文件为 WK2114 UART 1 拓展 4的 驱动程序, 基于STM32F2 系列CPU,通过终端收发数据, 测试通过可用。
  • 可以通过模式选择使得该芯片工作于以上任何一种主接口模式,将选 定的主接口扩展为4个增强功能的UART。 扩展的子通道的UART具备如下功能特点: 1.每个子通道UART的波特率、字长、校验格式可以独立设置,最高可以提供...

    一、WK2168介绍
    WK2168是首款具备256级FIFO的低功耗并支持 UART/SPITM/IIC/8位并行总线接口的
    4通道UART器件。可以通过模式选择使得该芯片工作于以上任何一种主接口模式,将选
    定的主接口扩展为4个增强功能的UART。
    扩展的子通道的UART具备如下功能特点:
    1.每个子通道UART的波特率、字长、校验格式可以独立设置,最高可以提供2Mbps
    的通信速率。
    2.每个子通道可以独立设置工作在IrDA红外通信、 RS-485自动收发控制、 9位网络
    地址自动识别、软件/硬件自动流量控制等高级工作模式下。
    3.每个子通道具备收/发独立的256 级FIFO, FIFO的中断可按用户需求进行编程触
    发点且具备超时中断功能。
    WK2168采用LQFP48绿色环保的无铅封装,可以工作在2.5~5.0V的宽工作电压范围,
    具备可配置自动休眠/唤醒功能
    二、硬件连接
    在这里插入图片描述
    在这里插入图片描述
    三、驱动代码
    main.c

    #include "sys.h"
    #include "delay.h"
    #include "usart.h"
    #include "led.h" 
    #include "wk2168.h"
    
    
    
    
    
    int main(void)
    {	
    	//wk2xxx相关定义
    	u8 sendTimeCnt;
    	u16 ledCnt;
    	u8 dat1;
    	u8 sendData[5]={0x01,0x02,0x03,0x04,0x05};
    	
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    	delay_init();	
    	uart_init(115200);
    	led_init();	
    	wk2168_init();	
    	wk2168_exit_init();
    
    /*读写GNEA,测试主接口通信是否成功*/
    	dat1=wk2168_read_g_reg(WK2XXX_GENA);
    	printf("gena=0x%x.\r\n",dat1);
    
    
    	/*初始化子串口*/
    	wk2168_sub_uart_init(1);
    	wk2168_sub_uart_init(2);
    	wk2168_sub_uart_init(3);
    	wk2168_sub_uart_init(4);
    	/*设置子串口波特率*/
    	wk2168_set_baudrate(1,B9600);
    	wk2168_set_baudrate(2,B9600);
    	wk2168_set_baudrate(3,B9600);
    	wk2168_set_baudrate(4,B9600);
    	/*使能485*/
    	wk2168_set_rs485(1);
    	wk2168_set_rs485(2);
    	wk2168_set_rs485(3);
    	wk2168_set_rs485(4);
    
    	
    	while(1)
    	{
    		
    		sendTimeCnt++;
    		if(sendTimeCnt>=100)
    		{
    			sendTimeCnt=0;
    			wk2168_exti_disable();		
    			wk2168_write_s_fifo(1,sendData,sizeof(sendData));
    			wk2168_write_s_fifo(2,sendData,sizeof(sendData));
    			wk2168_write_s_fifo(3,sendData,sizeof(sendData));
    			wk2168_write_s_fifo(4,sendData,sizeof(sendData));
    			wk2168_exti_enable();				
    			
    		}
    	
    		
    		ledCnt++;
    		if(ledCnt>=50)
    		{
    			ledCnt=0;
    			turn_prog_led();
    		}
    		
    		delay_ms(10);
    	}
    }
    
    

    wk2168.c

    #include "wk2168.h"
    #include "delay.h"
    
    
    void wk2168_init(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	SPI_InitTypeDef SPI_InitStructure;
    	
    	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB | RCC_APB2Periph_SPI1, ENABLE );	
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;//PA0--INT#
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
    	GPIO_Init( GPIOB, &GPIO_InitStructure );
    	
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//SPI1_RST
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
    	GPIO_Init( GPIOB, &GPIO_InitStructure );
    	GPIO_SetBits(GPIOB,GPIO_Pin_0);
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;//SPI1_CS
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
    	GPIO_Init( GPIOA, &GPIO_InitStructure );
    	GPIO_SetBits(GPIOA,GPIO_Pin_4);
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//SPI1_SCK
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init( GPIOA, &GPIO_InitStructure );	
    
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;//SPI1_MISO
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;		
    	GPIO_Init( GPIOA, &GPIO_InitStructure );	
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;//SPI1_MOSI
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;		
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init( GPIOA, &GPIO_InitStructure );
    	
    	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;	
    	
    	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;	
    
    	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;	
    	SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;	
    	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;	
    	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;	
    	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
    	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	
    	SPI_InitStructure.SPI_CRCPolynomial = 7;
    	SPI_Init( SPI1, &SPI_InitStructure );
    
    	SPI_Cmd( SPI1, ENABLE );
    	
    
    	wk2168_rst=0;
    	delay_ms(50);
    	wk2168_rst=1;
    	delay_ms(10);
    	
    }
     
    void wk2168_exit_init()
    {
     	EXTI_InitTypeDef EXTI_InitStructure;
     	NVIC_InitTypeDef NVIC_InitStructure;
    
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	//使能复用功能时钟
    
        
      	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);//下降沿触发
    
      	EXTI_InitStructure.EXTI_Line=EXTI_Line1;	
      	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
      	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
      	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
      	EXTI_Init(&EXTI_InitStructure);	 	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
    
        NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;			//使能按键KEY2所在的外部中断通道
      	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;	//抢占优先级2, 
      	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;					//子优先级2
      	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
      	NVIC_Init(&NVIC_InitStructure);	
    }
    void wk2168_exti_enable(void)
    {
    	NVIC_InitTypeDef NVIC_InitStructure;
    	
    	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;			//使能按键KEY2所在的外部中断通道
      	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;	//抢占优先级2, 
      	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;					//子优先级2
      	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
      	NVIC_Init(&NVIC_InitStructure);
    }
    
    void wk2168_exti_disable(void)
    {
    	NVIC_InitTypeDef NVIC_InitStructure;
    	
    	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;			//使能按键KEY2所在的外部中断通道
      	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;	//抢占优先级2, 
      	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;					//子优先级2
      	NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;								//使能外部中断通道
      	NVIC_Init(&NVIC_InitStructure);
    }
    //外部中断0服务程序 
    void EXTI1_IRQHandler(void)
    {
    	u8 gifr,rxbuf[256];
    	int rxlen;	
    	if(EXTI_GetFlagStatus(EXTI_Line1)!= RESET)
    	{
    		gifr=wk2168_read_g_reg(WK2XXX_GIFR);/**/
    		do{
    			if(gifr&WK2XXX_UT1INT)//判断子串口1是否有中断
    			{ 
    				/*数据处理*/
    				/*数据接收*/
    				rxlen=wk2168_rec_data(1,rxbuf);//一次接收的数据不会超过256Byte
    				/*数据发送*/
    				//把接收的数据发送出去
    				wk2168_send_data(1,rxlen,rxbuf);
    
    			}
    			
    			if(gifr&WK2XXX_UT2INT)//判断子串口2是否有中断
    			{
    				/*数据接收*/
    				rxlen=wk2168_rec_data(2,rxbuf);//一次接收的数据不会超过256Byte
    				/*数据发送*/
    				//把接收的数据发送出去
    				wk2168_send_data(2,rxlen,rxbuf);
    			
    			  }
    			if(gifr&WK2XXX_UT3INT)//判断子串口3是否有中断
    			{
    				/*数据接收*/
    				rxlen=wk2168_rec_data(3,rxbuf);//一次接收的数据不会超过256Byte
    				/*数据发送*/
    				//把接收的数据发送出去
    				wk2168_send_data(3,rxlen,rxbuf);
    				// printf("port!!!!\n");
    			}
    			if(gifr&WK2XXX_UT4INT)//判断子串口4是否有中断
    			{
    				/*数据接收*/
    				rxlen=wk2168_rec_data(4,rxbuf);//一次接收的数据不会超过256Byte
    				/*数据发送*/
    				//把接收的数据发送出去
    				wk2168_send_data(4,rxlen,rxbuf);
    			}
    			
    			gifr=wk2168_read_g_reg(WK2XXX_GIFR);
    			//printf("IN EXTI2_IRQ GIFR:0X%X !!!\n",gifr);
    		}while(gifr&0x0f);					
    		EXTI_ClearITPendingBit(EXTI_Line1); //清除LINE0上的中断标志位  
    	}
    }
    /* SPI交换一个字节接口 */
    u8 wk2168_spi_read_write_byte(u8 TxData)
    {
    	u8 retry=0;				 	
    	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
    	{
    		retry++;
    		if(retry>200)return 0;
    	}			  
    	SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个数据
    	retry=0;
    
    	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
    	{
    		retry++;
    		if(retry>200)return 0;
    	}	  						    
    	return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据	
    }
    
    /*************************************************************************/
    //函数功能:设置CS信号为高电平
    /*************************************************************************/
    void wk2168_cs_high(void)
    {
    	GPIO_SetBits(GPIOA,GPIO_Pin_4);
    }
    /*************************************************************************/
    //函数功能:设置CS信号为低电平
    /*************************************************************************/
    void wk2168_cs_low(void)
    {
    	GPIO_ResetBits(GPIOA,GPIO_Pin_4);
    }
    /***************************wk2168_write_g_reg***********************************/
    //函数功能:写全局寄存器函数(前提是该寄存器可写,
    //某些寄存器如果你写1,可能会自动置1,具体见数据手册)
    //参数:
    //      greg:为全局寄存器的地址
    //      dat:为写入寄存器的数据
    //***********************************************************************/
    void wk2168_write_g_reg(unsigned char greg,unsigned char dat)
    {	 
    	u8 cmd;
    	cmd=0|greg;
    	wk2168_cs_low();//拉低cs信号
    	wk2168_spi_read_write_byte(cmd);	//写指令,对于指令的构成见数据手册
    	wk2168_spi_read_write_byte(dat);//写数据
    	wk2168_cs_high();//拉高cs信号
    }
    /****************************wk2168_read_g_reg***********************************/
    //函数功能:读全局寄存器
    //参数:
    //      greg:为全局寄存器的地址
    //      rec:返回的寄存器值
    //***********************************************************************/
    u8 wk2168_read_g_reg(unsigned char greg)
    {	 
    	u8 cmd,rec;
    	cmd=0x40|greg;
    	wk2168_cs_low();//拉低cs信号
    	wk2168_spi_read_write_byte(cmd);	//写指令,对于指令的构成见数据手册
    	rec=wk2168_spi_read_write_byte(0);//写数据
    	wk2168_cs_high();//拉高cs信号							
    	return rec;
    }
    
    /**************************wk2168_write_s_reg***********************************/
    //函数功能:
    //参数:port:为子串口
    //      sreg:为子串口寄存器
    //      dat:为写入寄存器的数据
    //注意:在子串口被打通的情况下,向FDAT写入的数据会通过TX引脚输出
    //**********************************************************************/
    void wk2168_write_s_reg(u8 port,u8 sreg,u8 dat)
    {	 
    	u8 cmd;
    	cmd=0x0|((port-1)<<4)|sreg;
    	wk2168_cs_low();//拉低cs信号
    	wk2168_spi_read_write_byte(cmd);	//写指令,对于指令的构成见数据手册
    	wk2168_spi_read_write_byte(dat);//写数据
    	wk2168_cs_high();//拉高cs信号
    }
    
    /**************************wk2168_read_s_reg***********************************/
    //函数功能:读子串口寄存器
    //参数:port为子串口端口号
    //      sreg:为子串口寄存器地址
    //      rec:返回的寄存器值
    //**********************************************************************/
    u8 wk2168_read_s_reg(u8 port,u8 sreg)
    {	 
    	u8 cmd,rec;
    	cmd=0x40|((port-1)<<4)|sreg;
    	wk2168_cs_low();//拉低cs信号
    	wk2168_spi_read_write_byte(cmd);	//写指令,对于指令的构成见数据手册
    	rec=wk2168_spi_read_write_byte(0);//写数据
    	wk2168_cs_high();	//拉高cs信号							
    	return rec;
    }
    /************************wk2168_write_s_fifo***********************************/
    //函数功能:向子串口fifo写入需要发送的数据
    //参数:port:为子串口
    //      *dat:写入数据
    //      num:为写入数据的个数,单次不超过256
    //注意:通过该方式写入的数据,被直接写入子串口的缓存FIFO,然后被发送
    //*********************************************************************/
    void wk2168_write_s_fifo(u8 port,u8 *dat,int num)
    {	 
    	u8 cmd;
    	int i;
    	cmd=0x80|((port-1)<<4);
    	if(num>0)
    	{
    		wk2168_cs_low();//拉低cs信号
    		wk2168_spi_read_write_byte(cmd); //写指令,对于指令构成见数据手册
    		for(i=0;i<num;i++)
    		{
    			wk2168_spi_read_write_byte( *(dat+i));//写数据
    		}
    		wk2168_cs_high();//拉高cs信号
    	}
    }
    
    /************************wk2168_read_s_fifo***********************************/
    //函数功能:从子串口的fifo中读出接收到的数据
    //参数:port:为子串口
    //      *rec:接收到的数据
    //      num:读出的数据个数。
    //注意:通过该方式读出子串口缓存中的数据。单次不能超过256
    //*********************************************************************/
    void wk2168_read_s_fifo(u8 port,u8 *rec,int num)
    {
    	u8 cmd;
    	int n;
    	cmd=0xc0|((port-1)<<4);
    	if(num>0)
    	{
    		wk2168_cs_low();//拉低cs信号
    		wk2168_spi_read_write_byte(cmd);
    		for(n=0;n<num;n++)
    		{	
    			*(rec+n)=wk2168_spi_read_write_byte(0);	
    		}
    		wk2168_cs_high();//拉高cs信号
    	}
    }
    
    
    /*******WkInit*******************************************/
    //函数功能:初始化子串口
    /*******************************************************/
    void wk2168_sub_uart_init(u8 port)
    {
    	u8 gena,grst,gier,sier,scr;
    	//使能子串口时钟
    	gena=wk2168_read_g_reg(WK2XXX_GENA);
    	gena=gena|(1<<(port-1));
    	wk2168_write_g_reg(WK2XXX_GENA,gena);
    	//软件复位子串口
    	grst=wk2168_read_g_reg(WK2XXX_GRST);
    	grst=grst|(1<<(port-1));
    	wk2168_write_g_reg(WK2XXX_GRST,grst);
    	//使能串口总中断
    	gier=wk2168_read_g_reg(WK2XXX_GIER);
    	gier=gier|(1<<(port-1));
    	wk2168_write_g_reg(WK2XXX_GIER,gier);
    	//使能子串口接收触点中断和超时中断
    	sier=wk2168_read_s_reg(port,WK2XXX_SIER); 
    	sier |= WK2XXX_RFTRIG_IEN|WK2XXX_RXOUT_IEN;
    	wk2168_write_s_reg(port,WK2XXX_SIER,sier);
    	//初始化FIFO和设置固定中断触点
    	wk2168_write_s_reg(port,WK2XXX_FCR,0XFF);  
    	//设置任意中断触点,如果下面的设置有效,
    	//那么上面FCR寄存器中断的固定中断触点将失效
    	wk2168_write_s_reg(port,WK2XXX_SPAGE,1);//切换到page1
    	wk2168_write_s_reg(port,WK2XXX_RFTL,0X40);//设置接收触点为64个字节
    	wk2168_write_s_reg(port,WK2XXX_TFTL,0X10);//设置发送触点为16个字节
    	wk2168_write_s_reg(port,WK2XXX_SPAGE,0);//切换到page0 
    	//使能子串口的发送和接收使能
    	scr=wk2168_read_s_reg(port,WK2XXX_SCR); 
    	scr|=WK2XXX_TXEN|WK2XXX_RXEN;
    	wk2168_write_s_reg(port,WK2XXX_SCR,scr);	  		
    }
    
    /******************************wk2168_sub_uart_deinit*******************************************/
    //函数功能:初始化子串口
    /*********************************************************************************/
    void wk2168_sub_uart_deinit(u8 port)
    {
    	u8 gena,grst,gier;
    	//关闭子串口总时钟
    	gena=wk2168_read_g_reg(WK2XXX_GENA);
    	gena=gena&(~(1<<(port-1)));
    	wk2168_write_g_reg(WK2XXX_GENA,gena);
    	//使能子串口总中断
    	gier=wk2168_read_g_reg(WK2XXX_GIER);
    	gier=gier&(~(1<<(port-1)));
    	wk2168_write_g_reg(WK2XXX_GIER,gier);
    	//软件复位子串口
    	grst=wk2168_read_g_reg(WK2XXX_GRST);
    	grst=grst|(1<<(port-1));
    	wk2168_write_g_reg(WK2XXX_GRST,grst);
    	
    }
    
    /**************************wk2168_set_baudrate*******************************************************/
    //函数功能:设置子串口波特率函数、此函数中波特率的匹配值是根据11.0592Mhz下的外部晶振计算的
    // port:子串口号
    // baud:波特率大小.波特率表示方式,
    /**************************Wk2114SetBaud*******************************************************/
    void wk2168_set_baudrate(u8 port,enum WKBaud baud)
    {  
    	unsigned char baud1,baud0,pres,scr;
    	//如下波特率相应的寄存器值,是在外部时钟为11.0592mhz的情况下计算所得,如果使用其他晶振,需要重新计算
    	switch (baud) 
    	{
    		case B600:
    			baud1=0x4;
    			baud0=0x7f;
    			pres=0;
    			break;
    		case B1200:
    			baud1=0x2;
    			baud0=0x3F;
    			pres=0;
    			break;
    		case B2400:
    			baud1=0x1;
    			baud0=0x1f;
    			pres=0;
    			break;
    		case B4800:
    			baud1=0x00;
    			baud0=0x8f;
    			pres=0;
    			break;
    		case B9600:
    			baud1=0x00;
    			baud0=0x47;
    			pres=0;
    			break;
    		case B19200:
    			baud1=0x00;
    			baud0=0x23;
    			pres=0;
    			break;
    		case B38400:
    			baud1=0x00;
    			baud0=0x11;
    			pres=0;
    			break;
    		case B76800:
    			baud1=0x00;
    			baud0=0x08;
    			pres=0;
    			break;        
    		case B1800:
    			baud1=0x01;
    			baud0=0x7f;
    			pres=0;
    			break;
    		case B3600:
    			baud1=0x00;
    			baud0=0xbf;
    			pres=0;
    			break;
    		case B7200:
    			baud1=0x00;
    			baud0=0x5f;
    			pres=0;
    			break;
    		case B14400:
    			baud1=0x00;
    			baud0=0x2f;
    			pres=0;
    			break;
    		case B28800:
    			baud1=0x00;
    			baud0=0x17;
    			pres=0;
    			break;
    		case B57600:
    			baud1=0x00;
    			baud0=0x0b;
    			pres=0;
    			break;
    		case B115200:
    			baud1=0x00;
    			baud0=0x05;
    			pres=0;
    			break;
    		case B230400:
    			baud1=0x00;
    			baud0=0x02;
    			pres=0;
    			break;
    		default:
    			baud1=0x00;
    			baud0=0x00;
    			pres=0;
        }
    	//关掉子串口收发使能
    	scr=wk2168_read_s_reg(port,WK2XXX_SCR); 
    	wk2168_write_s_reg(port,WK2XXX_SCR,0);
    	//设置波特率相关寄存器
    	wk2168_write_s_reg(port,WK2XXX_SPAGE,1);//切换到page1
    	wk2168_write_s_reg(port,WK2XXX_BAUD1,baud1);
    	wk2168_write_s_reg(port,WK2XXX_BAUD0,baud0);
    	wk2168_write_s_reg(port,WK2XXX_PRES,pres);
    	wk2168_write_s_reg(port,WK2XXX_SPAGE,0);//切换到page0 
    	//使能子串口收发使能
    	wk2168_write_s_reg(port,WK2XXX_SCR,scr);
    }
    /**************************wk2168_get_tx_len*******************************************/
    //函数功能:获取子串口发送FIFO剩余空间长度
    // port:端口号
    // 返回值:发送FIFO剩余空间长度
    /**************************WK_Len********************************************/
    int wk2168_get_tx_len(u8 port)
    {
    	u8 fsr,tfcnt;
    	int len=0;
    	fsr  =wk2168_read_s_reg(port,WK2XXX_FSR);
    	tfcnt=wk2168_read_s_reg(port,WK2XXX_TFCNT);
    	if(fsr& WK2XXX_TFULL)
    	{ 
    		len=0;
    	}
    	else
    	{
    		len=256-tfcnt;
    	}
    	return len;
    }
    
    /**************************wk2168_send_data*******************************************/
    //函数功能:通过子串口发送固定长度数据
    // port:端口号
    // len:单次发送长度不超过256
    // 
    /**************************wk2168_send_data********************************************/
    int wk2168_send_data(u8 port,int len,u8 *sendbuf)
    {
    	
    #if 1
    	wk2168_write_s_fifo(port,sendbuf,len);//通过fifo方式发送数据
    #else
    	int num=len;
    	for(num=0;num<len;num++)
    	{
    		wk2168_write_s_reg(port,WK2XXX_FDAT,*(sendbuf+num));
    	}
    #endif	
    	return 0;
    }
    
    /**************************wk2168_rec_data*******************************************/
    //函数功能:读取子串口fifo中的数据
    // port:端口号
    // recbuf:接收到的数据
    // 返回值:接收数据的长度
    /**************************wk2168_rec_data********************************************/
    int wk2168_rec_data(u8 port,u8 *recbuf)
    {
    	u8  fsr=0,rfcnt=0,rfcnt2=0,sifr=0;
    	int len=0;
    	sifr=wk2168_read_s_reg(port,WK2XXX_SIFR);
    	
    
    	if((sifr&WK2XXX_RFTRIG_INT)||(sifr&WK2XXX_RXOVT_INT))//有接收中断和接收超时中断
    	{ 
    		fsr  =wk2168_read_s_reg(port,WK2XXX_FSR);
    		rfcnt=wk2168_read_s_reg(port,WK2XXX_RFCNT);
    		rfcnt2=wk2168_read_s_reg(port,WK2XXX_RFCNT);
    		//printf("rfcnt=0x%x.\n",rfcnt);
    		/*判断fifo中数据个数*/
    		if(fsr& WK2XXX_RDAT)
    		{ 
    			if(!(rfcnt2>=rfcnt))
    			{
    				rfcnt=rfcnt2;
    			}
    			len=(rfcnt==0)?256:rfcnt;
    		}
    #if 1
    		wk2168_read_s_fifo(port,recbuf,len);
    #else
    		for(n=0;n<len;n++)
    		 *(recbuf+n)=wk2168_read_s_reg(port,WK2XXX_FDAT);
    #endif	
    		return len;
    	}
    	else
    	{
    		len=0;
    		return len;
    	}
    }
    
    /**************************wk2168_set_rs485*******************************************************/
    //函数功能:设置子串口RS485的收发转换函数,使用RTS引脚控制485电平转换芯片的收发
    // port:子串口号
    // 
    //注意:只有WK2168/WK2204支持该功能
    /**************************wk2168_set_rs485*******************************************************/
    void wk2168_set_rs485(u8 port)
    {   
    	wk2168_write_s_reg(port,WK2XXX_RS485,0x02);//
    	//wk2168_write_s_reg(port,WK2XXX_RS485,0x03);//
    	wk2168_write_s_reg(port,WK2XXX_SPAGE,1);//切换到page1
    	wk2168_write_s_reg(port,WK2XXX_RTSDLY,0x01);
    	wk2168_write_s_reg(port,WK2XXX_SPAGE,0);//切换到page0 
    }
    /**************************wk2168_rts_cts*******************************************************/
    //函数功能:硬件自动流量控制,需要子设备的支持
    // port:子串口号
    // 
    //注意:只有WK2168/WK2204支持该功能
    /**************************wk2168_rts_cts*******************************************************/
    void wk2168_rts_cts(u8 port)
    {   
    	wk2168_write_s_reg(port,WK2XXX_FWCR,0x30);//
    	wk2168_write_s_reg(port,WK2XXX_SPAGE,1);//切换到page1
    	wk2168_write_s_reg(port,WK2XXX_FWTH,0XF0);//停止接收触点
    	wk2168_write_s_reg(port,WK2XXX_FWTL,0X20);//继续接收触点
    	wk2168_write_s_reg(port,WK2XXX_SPAGE,0);//切换到page0 
    }
    
    

    四、完整工程下载

    完整工程下载,请点击

    展开全文
  • WK系列串口扩展芯片详解(含电路例程)  很多单片机,比如51单片机,只有一个或两个串口。所以,有时会遇到串口不够用的情况,这时候可以换一款串口更多的单片机。而有时你又不想换一款单片机,那可以使用本文要介绍...
  • STM32使用HAL库硬件SPI驱动WK2124一拖四SPI转四路串口芯片 STM32基础工程生成 首先使用STM32CUBEMX生成STM32的基础工程,配置时钟到72M主频: 配置SPI前,首先查看WK2124芯片手册,手册里面说明了WK2124的SPI...
  • 本例程是基于主控stm32,实现spi串口扩展4个子串口,基于wk2124芯片。 本例程是基于主控stm32,实现spi串口扩展4个子串口,基于wk2124芯片
  • WK2124是SPITM接口的4通道UART器件,WK2124实现SPI桥接/扩展4个增强功能串口(UART)的功能。 扩展的子通道的UART具备如下功能特点: 每个子通道UART的波特率、字长、校验格式可以独立设置,最高可以提供2Mbps的...
  • 移植SPI扩展4串口芯片WK2124官方程序到STM32F103C8 Cube HAL版测试成功
  • WK2xxx芯片驱动程序

    2020-12-09 11:51:36
    基于linux系统开发的驱动程序,spi扩展串口驱动源码。可以用于linux3.x版本的嵌入式系统中。
  • 本程序基于串口扩展芯片WK2204.实现了i2c转4个串口。本源程序在为开微电子的网站也有。
  • 基于一款 wk2168芯片串口扩展

    千次阅读 2019-06-21 14:15:00
    串口扩展芯片应用介绍 一、 概述 随着嵌入式系统的功能越来越强大,搭载的外围设备也不断的增加,为了方便系统的集成,现在的外围设备通常都提供了标准的通信接口。在这些标准接口当中最常用的就是我们比较熟悉的...
  • WK2114将一个标准3线异步串口(UART)扩展成为4个增强 功能串口(UART)。主接口UART在数据传输时主接口的UART可以通过引脚配置为红外通信模式。 扩展的子通道的UART具备如下功能特点: 每个子通道UART的波特率、...
  • 该程序基于wk2124芯片,主接口为spi,扩展4个子串口实现数据收发
  • WK2124 linux 驱动移植

    千次阅读 2019-05-17 10:34:54
    目前WK系列能实现SPI扩展uart的芯片包括 WK2124、WK2204、WK2168、WK2132。目前WK2124、WK2204、WK2168能实现SPI扩展4路UART,WK2132能实现扩展2路UART。目前这几款芯片使用的都是相同的linux驱动。 WK系列扩展的子...
  • wk2xxx_spi_v2.3(double).rar

    2020-04-09 15:45:02
    本驱动是在rk3288上调试的两片WK2124扩展8串口的驱动程序。两片芯片挂在同一spi总线,共用一个IRQ外部中断。
  • WK2114将一个标准3线异步串口(UART)扩展成为4个增强 功能串口(UART)。主接口UART在数据传输时主接口的UART可以通过引脚配置为红外通信模式。 扩展的子通道的UART具备如下功能特点: 每个子通道UART的波特率、...
  • wk2124_2204.zip

    2021-09-14 16:30:23
    wk2124 支持4uart 串口扩展芯片
  • UART或SPI或I2C扩展为4路UART串口, 是首款具备256级FIFO的低功耗并支持 UART/spiTM/IIC位并行总线接口的4通道UART器件。 可以通过模式选择使得该芯片工作于以上任何一种主接口模式,将选定的主接口扩展为4个增强...

空空如也

空空如也

1 2 3 4 5
收藏数 92
精华内容 36
关键字:

串口扩展芯片wk2124