/* * wk2xxx.c */ #include "wk2xxx.h" // #define WK2124 #define WK2114 /// 移植修改区域 #define WK2124_RST1_GPIO_Port GPIOA #define WK2124_RST1_Pin GPIO_PIN_15 #define WK2124_CS1_GPIO_Port GPIOA #define WK2124_CS1_Pin GPIO_PIN_15 // 拉低RST引脚 #define WK_GPIO_RST_L() HAL_GPIO_WritePin( WK2124_RST1_GPIO_Port, WK2124_RST1_Pin, GPIO_PIN_RESET ) // 拉高RST引脚 #define WK_GPIO_RST_H() HAL_GPIO_WritePin( WK2124_RST1_GPIO_Port, WK2124_RST1_Pin, GPIO_PIN_SET ) #ifdef WK2124 #include "spi.h" #define WK_SPI_Handle ( &hspi2 ) #endif #ifdef WK2114 #include "usart.h" #define WK_Uart_Handle ( &huart2 ) #endif // 片选引脚 拉低 拉高 #ifdef WK2124 #define WK_GPIO_SEL_L() HAL_GPIO_WritePin( WK2124_CS1_GPIO_Port, WK2124_CS1_Pin, GPIO_PIN_RESET ) #define WK_GPIO_SEL_H() HAL_GPIO_WritePin( WK2124_CS1_GPIO_Port, WK2124_CS1_Pin, GPIO_PIN_SET ) #endif #ifdef WK2114 #define WK_GPIO_SEL_L() #define WK_GPIO_SEL_H() #endif static void wk_delay_ms(uint32_t nms) { HAL_Delay(nms); } static uint8_t WK_SPI_ReadWriteByte(uint8_t TxData) { uint8_t RxData = 0X00; #ifdef WK2124 if ( HAL_SPI_TransmitReceive(WK_SPI_Handle, &TxData, &RxData, 1, 10) != HAL_OK ) { RxData = 0XFF; } #endif #ifdef WK2114 /* ???? */ if ( HAL_Uart_Transmit(WK_Uart_Handle, &TxData, 1, 10) != HAL_OK ) { RxData = 0XFF; } if ( HAL_UART_Receive(WK_Uart_Handle, &RxData, 1, 100) != HAL_OK ) { RxData = 0XFF; } #endif return RxData; } /// 驱动程序代码 void WK_Port(void) { /* Hard Reset */ WK_Rst(); /* uart 需要自适应串口, spi无需此操作*/ WK_SPI_ReadWriteByte( 0x55 ); // init ports WK_PortInit(1, 11059200, 9600); // 晶振 = 11.0592MHz ,这个值根据实际进行修改 WK_PortInit(2, 11059200, 9600); WK_PortInit(3, 11059200, 9600); WK_PortInit(4, 11059200, 9600); } /// 硬件复位(拉低复位引脚最低10毫秒进行复位) void WK_Rst(void) { WK_GPIO_RST_L( ); wk_delay_ms( 50 ); WK_GPIO_RST_H( ); wk_delay_ms( 50 ); } void WK_WriteGReg( uint8_t reg, uint8_t value ) { WK_GPIO_SEL_L( ); WK_SPI_ReadWriteByte( reg ); WK_SPI_ReadWriteByte( value ); WK_GPIO_SEL_H( ); } uint8_t WK_ReadGReg( uint8_t reg ) { uint8_t value = 0X00; WK_GPIO_SEL_L( ); WK_SPI_ReadWriteByte( 0X40 | reg ); value = WK_SPI_ReadWriteByte( 0X00 ); WK_GPIO_SEL_H( ); return value; } void WK_WriteSReg( uint8_t port, uint8_t reg, uint8_t value ) { WK_GPIO_SEL_L( ); WK_SPI_ReadWriteByte( ((port - 1) << 4) | reg ); WK_SPI_ReadWriteByte( value ); WK_GPIO_SEL_H( ); } uint8_t WK_ReadSReg( uint8_t port, uint8_t reg ) { uint8_t value = 0X00; WK_GPIO_SEL_L( ); WK_SPI_ReadWriteByte(0X40 | ((port - 1) << 4) | reg); value = WK_SPI_ReadWriteByte( 0X00 ); WK_GPIO_SEL_H( ); return value; } void WK_WriteFIFO( uint8_t port, const void* buf, uint16_t len ) { const uint8_t* p = (const uint8_t *)buf; WK_GPIO_SEL_L( ); WK_SPI_ReadWriteByte(0X80 | ((port - 1) << 4)); while (len--) { WK_SPI_ReadWriteByte(*p++); } WK_GPIO_SEL_H( ); } void WK_ReadFIFO( uint8_t port, void* buf, uint16_t len ) { uint8_t* p = (uint8_t *)buf; WK_GPIO_SEL_L( ); WK_SPI_ReadWriteByte(0XC0 | ((port - 1) << 4)); while (len--) { *p++ = WK_SPI_ReadWriteByte(0X00); } WK_GPIO_SEL_H( ); } void WK_PortCalcBaudrate( uint32_t fosc, uint32_t baudrate, uint8_t* BAUD0, uint8_t* BAUD1, uint8_t* PRES ) { float value = (float)fosc / (float)(baudrate << 4); *BAUD0 = (((uint32_t)value) - 1) & 0XFF; *BAUD1 = ((((uint32_t)value) - 1) >> 8) & 0XFF; *PRES = ((uint32_t)(value * 10)) % 10; } uint16_t WK_PortSendData( uint8_t port, const void* buf, uint16_t len ) { uint8_t state = 0; uint16_t nsend = 0; state = WK_ReadSReg( port, WK2XXX_FSR ); if (state & WK2XXX_TFULL) // 发送FIFO满 { nsend = 0; } else { state = WK_ReadSReg( port, WK2XXX_TFCNT ); // 读取发送FIFO已用空间 nsend = 256 - state; nsend = nsend >= len ? len : nsend; WK_WriteFIFO(port, buf, nsend); // 将待发送的数据写入FIFO } return nsend; // 返回实际发送成功的数据量 } uint16_t WK_PortRecvData( uint8_t port, void* buf, uint16_t len ) { uint8_t state = 0; uint8_t nread = 0; state = WK_ReadSReg( port, WK2XXX_FSR ); if ( state & WK2XXX_RDAT ) // 接收FIFO非空 { nread = WK_ReadSReg( port, WK2XXX_RFCNT ); // 查询FIFO中的数据量 ?恰好256个? if ( nread == 0 ) { nread= 256; }else{ nread = len >= nread ? nread : len; } WK_ReadFIFO( port, buf, nread ); // 读取FIFO中的数据 } return nread; // 返回实际读取到的数据量 } void WK_PortInit( uint8_t port, uint32_t fosc, uint32_t baudrate ) { uint8_t BAUD0 = 0, BAUD1 = 0, PRES = 0, value = 0, ret = 0; /* 使能子串口时钟 */ value = WK_ReadGReg( WK2XXX_GENA ); value |= (1 << (port - 1)); WK_WriteGReg( WK2XXX_GENA, value ); ret = WK_ReadGReg( WK2XXX_GENA ); /* 软件复位子串口 */ value = WK_ReadGReg( WK2XXX_GRST ); value |= (1 << (port - 1)); WK_WriteGReg( WK2XXX_GRST, value ); ret = WK_ReadGReg( WK2XXX_GRST ); /* 使能子串口总中断 */ value = WK_ReadGReg( WK2XXX_GIER ); value |= (1 << (port - 1)); WK_WriteGReg( WK2XXX_GIER, value ); ret = WK_ReadGReg( WK2XXX_GIER ); /* 使能子串口FIFO相关中断 */ value = WK_ReadSReg( port, WK2XXX_SIER ); value |= WK2XXX_RFTRIG_IEN; // 接收FIFO触点中断 // value |= WK2XXX_TFTRIG_IEN; // 发送FIFO触点中断 // value |= WK2XXX_RXOUT_IEN; // 接收FIFO超时中断 WK_WriteSReg( port, WK2XXX_SIER, value ); ret = WK_ReadSReg( port, WK2XXX_SIER ); /* 设置FCR寄存器 */ value = 0; value |= (1 << 0); // 复位接收FIFO value |= (1 << 1); // 复位发送FIFO value |= (1 << 2); // 使能接收FIFO(这一步必须) value |= (1 << 3); // 使能发送FIFO(这一步必须) value |= (0 << 4); // 设置接收FIFO触点固定为8字节 value |= (0 << 6); // 设置发送FIFO触点固定为8字节 WK_WriteSReg( port, WK2XXX_FCR, value ); ret = WK_ReadSReg( port, WK2XXX_FCR ); /* 切换到 page1 设置中断触点和波特率 */ WK_WriteSReg( port, WK2XXX_SPAGE, 1 ); ret = WK_ReadSReg( port, WK2XXX_SPAGE ); WK_WriteSReg( port, WK2XXX_RFTL, 10 ); // 设置接收触点为10个字节 ret = WK_ReadSReg( port, WK2XXX_RFTL ); WK_WriteSReg( port, WK2XXX_TFTL, 10 ); // 设置发送触点为10个字节 ret = WK_ReadSReg( port, WK2XXX_TFTL ); WK_PortCalcBaudrate( fosc, baudrate, &BAUD0, &BAUD1, &PRES ); // 计算波特率 WK_WriteSReg( port, WK2XXX_BAUD1, BAUD1 ); // 设置BAUD1 ret = WK_ReadSReg( port, WK2XXX_BAUD1 ); WK_WriteSReg( port, WK2XXX_BAUD0, BAUD0 ); // 设置BAUD0 ret = WK_ReadSReg( port, WK2XXX_BAUD0 ); WK_WriteSReg( port, WK2XXX_PRES, PRES ); // 设置PRES ret = WK_ReadSReg( port, WK2XXX_PRES ); /* 切换回page0 */ WK_WriteSReg( port, WK2XXX_SPAGE, 0 ); ret = WK_ReadSReg( port, WK2XXX_SPAGE ); /* 使能子串口收发 */ value = WK_ReadSReg( port, WK2XXX_SCR ); value |= WK2XXX_TXEN; value |= WK2XXX_RXEN; WK_WriteSReg( port, WK2XXX_SCR, value ); ret = WK_ReadSReg( port, WK2XXX_SCR ); } // 如果irq引脚接入了单片机的外部中断引脚,将该函数放入外部中断处理函数内。 // 对于WK2124所开启的中断可以这么处理: void WK_IRQHandler( void ) { int i = 0; uint8_t GIFR = 0, SIFR = 0; /* 读取子串口全局中断寄存器 , 返回子串口 GIFR : Global Interupt Flag Register, */ GIFR = WK_ReadGReg( WK2XXX_GIFR ); // 查询4个子串口是否发生中断 for (i = 0; i < 4; i++) { if ((GIFR >> i) & 0X01) { /* 子串口中断标志寄存器 SIFR : Sub Uart Interupt Flag Register */ SIFR = WK_ReadSReg((i + 1), WK2XXX_SIFR); // 有接收FIFO触点中断, 置位,接收非空 if ( SIFR & WK2XXX_RFTRIG_INT ) { /* 调用WK_PortRecvData接收数据, 映射到指定的buff , */ } // 有接收FIFO超时中断, 接收超时 if ( SIFR & WK2XXX_RXOVT_INT ) { } // 有发送FIFO触点中断, 置位子串口标记有发送 if ( SIFR & WK2XXX_TFTRIG_INT ) { } // 有发送FIFO空中断,置位子串口标记 if ( SIFR & WK2XXX_TFEMPTY_INT ) { } /* 有接收FIFO数据错误中断, 置位子串口标记 重新发送对应串口操作 ? 需要子串口类记录上次发生 子串口,要能调用父串口操作发送FIFO */ if ( SIFR & WK2XXX_FERR_INT ) { } } } } /*************************************************************************/ // 函数功能: 此函数主要是通过读写wk2xxx的寄存器来判断主接口的通信时序是否有问题 // 参数: 无 // 返回值: rv表示返回值,0成功 /*************************************************************************/ uint8_t Wk2xxx_Test(void) { uint8_t rec_data,rv; //主接口为SPI rec_data = WK_ReadSReg( WK2XXX_GPORT, WK2XXX_GENA ); if ( rec_data == 0x30 ) return rv; else { rv = 1; return rv; } } /* 初始化 int main() { int nrecv = 0; uint8_t buffer[256]; // 硬件复位一下 WK_Rst(); // 初始化四个端口 WK_PortInit(1, 11059200, 9600); // WK2124晶振我用的是11.0592MHz的,这个值根据实际进行修改 WK_PortInit(2, 11059200, 9600); WK_PortInit(3, 11059200, 9600); WK_PortInit(4, 11059200, 9600); // 发送数据 WK_PortSendData(1, "helloworld\r\n", 12); WK_PortSendData(2, "helloworld\r\n", 12); WK_PortSendData(3, "helloworld\r\n", 12); WK_PortSendData(4, "helloworld\r\n", 12); // 接收数据,轮询方式 nrecv = WK_PortRecvData(1, buffer, sizeof(buffer)); if(nrecv != 0) { // 处理数据 } } */ // /***************************************************************************/ // //本文件为WK2XXX系列串口扩展芯片的设备驱动程序,作为驱动参开demo。使用者可以根据自身的情况加以修改,完善。 // /***************************************************************************/ // #include "wk2xxx.h" // // #include "spi.h" // // #include "usart.h" // // #include "delay.h" // void WK2XXX_RST_Init(void) // { // GPIO_InitTypeDef GPIO_InitStructure; // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA,PD端口时钟 // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //PA.3 端口配置 // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz // GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA.3 // GPIO_SetBits(GPIOA,GPIO_Pin_3); //PA.3 输出高 // } // void WK2XXX_Reset_Init(void) // { // GPIO_SetBits(GPIOA,GPIO_Pin_3);//1 // GPIO_ResetBits(GPIOA,GPIO_Pin_3);//0 // delay_ms(10); // GPIO_SetBits(GPIOA,GPIO_Pin_3);//1 // delay_ms(100); // } // /*************************************************************************/ // //函数功能:初始化SPI片选信号CS,并把CS的默认状态设置为高电平 // // // // // /*************************************************************************/ // void SPI_CS_Init(void) // { // GPIO_InitTypeDef GPIO_InitStructure; // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA,PD端口时钟 // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_3; //PA.4 端口配置 // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz // GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA.4 // GPIO_SetBits(GPIOA,GPIO_Pin_4); //PA.4 输出高 // } // /*************************************************************************/ // //函数功能:初始化SPI总线,设置SPI总线为0模式 // /*************************************************************************/ // void SPI_BUS_Init(void) // { // SPI1_Init(); //初始化SPI // SPI1_SetSpeed(SPI_BaudRatePrescaler_8); //设置为10M时钟,高速模式 // } // /*************************************************************************/ // //函数功能:设置CS信号为高电平 // /*************************************************************************/ // void SPI_CS_H(void) // { // GPIO_SetBits(GPIOA,GPIO_Pin_4); // } // /*************************************************************************/ // //函数功能:设置CS信号为低电平 // /*************************************************************************/ // void SPI_CS_L(void) // { // GPIO_ResetBits(GPIOA,GPIO_Pin_4); // } // /*************************************************************************/ // //函数功能:初始化SPI接口 // /*************************************************************************/ // void WK2XXX_SPI_Init(void) // { // SPI_CS_Init(); // SPI_BUS_Init(); // } // /*************************************************************************/ // //函数功能:写寄存器函数(前提是该寄存器可写,某些寄存器如果你写1,可能会自动置1,具体见数据手册) // //参数:port:为子串口的数(C0C1) // // reg:为寄存器的地址(A3A2A1A0) // // dat:为写入寄存器的数据 // //注意:在子串口被打通的情况下,向FDAT写入的数据会通过TX引脚输出 // //*************************************************************************/ // void Wk2xxxWriteReg(unsigned char port,unsigned char reg,unsigned char dat) // { // SPI_CS_L();//片选使能 // SPI1_ReadWriteByte(((port-1)<<4)+reg); //写控制字节 // SPI1_ReadWriteByte(dat); //写数据 // SPI_CS_H();//片选无效 // } // /*************************************************************************/ // //函数功能:读寄存器函数 // //参数:port:为子串口的数(C0C1) // // reg:为寄存器的地址(A3A2A1A0) // // rec_data:为读取到的寄存器值 // //注意:在子串口被打通的情况下,读FDAT,实际上就是读取uart的rx接收的数据 // /*************************************************************************/ // unsigned char Wk2xxxReadReg(unsigned char port,unsigned char reg) // { // unsigned char rec_data; // SPI_CS_L(); //片选使能 // SPI1_ReadWriteByte(0x40+((port-1)<<4)+reg);//写控制字节,控制命令构成见数据手册 // rec_data=SPI1_ReadWriteByte(0);//接收返回的数据 // SPI_CS_H(); //片选无效 // return rec_data; // } // /**************************** Wk2xxxWriteFifo*********************************************/ // //函数功能:该函数为写FIFO函数,通过该函数写入的数据会直接进入子串口的发送FIFO,然后通过TX引脚发送 // //参数:port:为子串口的端口号(C0\C1) // // *wbuf:写入数据部分 // // len: 写入数据长度 // // // /*************************************************************************/ // void Wk2xxxWriteFifo(unsigned char port,unsigned char *wbuf,unsigned int len) // { unsigned char n; // SPI_CS_L(); // 片选有效 // SPI1_ReadWriteByte(0x80+((port-1)<<4)); //写FIFO控制指令 // for(n=0;n