1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
很多单片机,比如51单片机,只有一个或两个串口。所以,有时会遇到串口不够用的情况,这时候可以换一款串口更多的单片机。而有时你又不想换一款单片机,那可以使用本文要介绍的八扩展串口芯片CH438。芯片是沁恒的,沁恒的芯片用了挺多,很有特色,质量也是很棒的。二话不说,先上简介。 CH438芯片的特色,在于单芯片有8个扩展串口,每个串口有128字节的FIFO,这可以节省你的单片机的RAM,同时,不容易因为没读取接收缓冲里的数据而使缓冲区溢出。CH438的访问接口是并行口,用的引脚比较多,数据脚和地址脚可共用。外围简单,只需要一个晶振。上电路图 现在来上代码 int main(void) { uint8_t UARTx; InitSysClk(); //Initial system clock InitSysTick(); //Initial sysTick timer, interrupt once per millisecond PortConfig(); //IO Port configure, please modify this function to configure the IO port CH438_PinInit(); for (UARTx=0; UARTx<16; UARTx++) { CH438_UARTxInit(UARTx); } while (1) { CH438SerialsProcess(); } } /********************************************************************************************************* CH438 串口处理 *********************************************************************************************************/ void CH438SerialsProcess(void) { uint8_t UARTx; uint8_t res; for (UARTx=0; UARTx<16; UARTx++) { res = CH438_UARTxRcv(UARTx, CH438UARTRcvBuf, &CH438UARTRcvLen); if (res == 0) //Hardware error { break; } if (CH438UARTRcvLen) { CH438_UARTxSend(UARTx, CH438UARTRcvBuf, CH438UARTRcvLen); } } } 初始化时先调用CH438_PinInit()配置一下并口的IO口,然后调用一下CH438_UARTxInit(UARTx)配置各个串口,接下来就可以用CH438_UARTxRcv读取接收缓存里的数据,以及用CH438_UARTxSendByte和CH438_UARTxSend发送数据了。 CH438的驱动如下 /********************************************************************************************************* ** 功能: CH438引脚初始化 ** 输入: 无 ** 返回: 无 ** 说明: CH438引脚初始化 *********************************************************************************************************/ void CH438_PinInit() { CH438_CSHigh(); CH438_ALELow(); CH438_WRHigh(); CH438_RDHigh(); } /********************************************************************************************************* ** 功能: CH438写寄存器 ** 输入: Addr:寄存器地址 ** 输入: RegValue:寄存器值 ** 返回: 无 ** 说明: CH438写寄存器 *********************************************************************************************************/ void CH438_WriteReg(uint8_t Addr, uint8_t RegValue) { CH438_SetDPort(Addr); CH438_CSLow(); CH438_ALEHigh(); CH438_ALELow(); CH438_SetDPort(RegValue); CH438_WRLow(); CH438_WRHigh(); CH438_CSHigh(); } /********************************************************************************************************* ** 功能: CH438读寄存器 ** 输入: Addr:寄存器地址 ** 返回: 寄存器值 ** 说明: CH438读寄存器 *********************************************************************************************************/ uint8_t CH438_ReadReg(uint8_t Addr) { uint8_t Data; CH438_SetDPort(Addr); CH438_CSLow(); CH438_ALEHigh(); CH438_ALELow(); CH438_SetDPortIn(); CH438_RDLow(); Data = CH438_ReadDPort(); CH438_RDHigh(); CH438_CSHigh(); return (Data); } /********************************************************************************************************* ** 功能: 检测访问CH438芯片是否正常 ** 输入: 无 ** 返回: 0 异常; 1 正常 ** 说明: 通过往一个寄存器写入值,然后读出判断是否一致,来检测访问是否正常 *********************************************************************************************************/ uint8_t CH438_CheckRW() { static uint8_t CheckData=0; uint8_t Temp; CH438_WriteReg(REG_SCR_ADDR, CheckData); Temp = CH438_ReadReg(REG_SCR_ADDR); if (CheckData != Temp) { CheckData ++; CH438RWErrorFlag = 1; return 0; } CheckData ++; CH438RWErrorFlag = 0; return 1; } /********************************************************************************************************* ** 功能: 初始化CH438串口UARTx ** 输入: UARTx: UARTx, 0~7 ** 返回: 0 成功;1 失败,访问出错 ** 说明: 初始化CH438串口UARTx *********************************************************************************************************/ uint8_t CH438_UARTxInit(uint8_t UARTx) { uint16_t DL = CH438_CLK/12/16/UARTsBaud[UARTx]; uint8_t UARTxBase = UARTsBase[UARTx]; uint8_t LCR; if (!CH438_CheckRW()) { return (0); } //先复位UARTx CH438_WriteReg(UARTxBase+REG_IER_ADDR, 1<<7); //设置UARTx的波特率 LCR = CH438_ReadReg(UARTxBase+REG_LCR_ADDR); LCR |= (1<<7); CH438_WriteReg(UARTxBase+REG_LCR_ADDR, LCR); //DLAB置1 CH438_WriteReg(UARTxBase+REG_DLL_ADDR, DL); CH438_WriteReg(UARTxBase+REG_DLM_ADDR, DL >> 8); LCR &= ~(1<<7); CH438_WriteReg(UARTxBase+REG_LCR_ADDR, LCR); //DLA清0 //设置数据格式: 无校验; 1个停止位; 8个数据位 CH438_WriteReg(UARTxBase+REG_LCR_ADDR, (0 << 4) //校验模式 0:奇校验; 1:偶检验; 2:1检验; 3:0检验 | (0 << 3) //校验使能 0:禁能; 1:使能 | (0 << 2) //停止位 0:1个停止位; 1:2个停止位 | (3 << 0)); //字长. 0:5 bits; 1:six bits; 2:7 bits; 3:8 bits //使能FIFO模式,清空FIFO CH438_WriteReg(UARTxBase+REG_FCR_ADDR, 0x07); return (1); } /********************************************************************************************************* ** 功能: CH438 UARTx发送一个字节 ** 输入: UARTx: UARTx, 0~7 ** 输入: Data: 要发送的字节 ** 返回: 0 成功;1 失败,访问出错 ** 说明: 同步模式,发送完毕,函数才返回 *********************************************************************************************************/ uint8_t CH438_UARTxSendByte(uint8_t UARTx, uint8_t Data) { uint8_t UARTxBase = UARTsBase[UARTx]; if (!CH438_CheckRW()) { return (0); } while((CH438_ReadReg(UARTxBase+REG_LSR_ADDR) & (1<<5)) == 0); //等待发送保持寄存器THR空 CH438_WriteReg(UARTxBase+REG_THR_ADDR, Data); while((CH438_ReadReg(UARTxBase+REG_LSR_ADDR) & (1<<6)) == 0); //等待发送完毕 return (1); } /********************************************************************************************************* ** 功能: CH438 UARTx发送 ** 输入: UARTx: UARTx, 0~7 ** 输入: pData: 发送数据指针 ** 输入: Num: 发送字节数 ** 返回: 0 成功;1 失败,访问出错 ** 说明: 同步模式,发送完毕,函数才返回 *********************************************************************************************************/ uint8_t CH438_UARTxSend(uint8_t UARTx, uint8_t *pData, uint16_t Num) { uint8_t UARTxBase = UARTsBase[UARTx]; if (!CH438_CheckRW()) { return (0); } while (Num--) { while((CH438_ReadReg(UARTxBase+REG_LSR_ADDR) & (1<<5)) == 0); //等待发送保持寄存器THR空 CH438_WriteReg(UARTxBase+REG_THR_ADDR, *(pData++)); } while((CH438_ReadReg(UARTxBase+REG_LSR_ADDR) & (1<<6)) == 0); //等待发送完毕 return (1); } /********************************************************************************************************* ** 功能: CH438 UARTx发送字符串 ** 输入: UARTx: UARTx, 0~7 ** 输入: str: 要发送的字符串 ** 返回: 0 成功;1 失败,访问出错 ** 说明: 同步模式,发送完毕,函数才返回 *********************************************************************************************************/ uint8_t CH438_UARTxSendString(uint8_t UARTx, char *str) { uint8_t UARTxBase = UARTsBase[UARTx]; if (!CH438_CheckRW()) { return (0); } while (*str != ' |