沁恒八串口扩展芯片CH438详解
很多单片机,比如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;
uint8_t UARTxBase = UARTsBase;
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;
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;
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;
if (!CH438_CheckRW())
{
return (0);
}
while (*str != '\0')
{
while((CH438_ReadReg(UARTxBase+REG_LSR_ADDR) & (1<<5)) == 0); //等待发送保持寄存器THR空
CH438_WriteReg(UARTxBase+REG_THR_ADDR, *(str++));
}
while((CH438_ReadReg(UARTxBase+REG_LSR_ADDR) & (1<<6)) == 0); //等待发送完毕
return (1);
}
/*********************************************************************************************************
** 功能: CH438 UARTx读取数据
** 输入: UARTx: UARTx, 0~7
** 输出: pData: 存放读取数据的指针
** 输出: pRcvNum: 读取到的字节数
** 返回: 0 成功;1 失败,访问出错
** 说明: 同步模式,发送完毕,函数才返回
*********************************************************************************************************/
uint8_t CH438_UARTxRcv(uint8_t UARTx, uint8_t *pData, uint8_t *pRcvNum)
{
uint8_t RcvNum = 0;
uint8_t LSR;
uint8_t UARTxBase = UARTsBase;
if (!CH438_CheckRW())
{
return (0);
}
while (1)
{
LSR = CH438_ReadReg(UARTxBase+REG_LSR_ADDR);
if (LSR & (BIT_LSR_BREAKINT | BIT_LSR_FRAMEERR | BIT_LSR_PARERR | BIT_LSR_OVERR)) //接收错误
{
CH438_ReadReg(UARTxBase+REG_RBR_ADDR);
}
else if (LSR & BIT_LSR_DATARDY) //接收缓冲有数据
{
*pData++ = CH438_ReadReg(UARTxBase+REG_RBR_ADDR);
RcvNum ++;
}
else
{
break;
}
if (RcvNum == 128)
{
break;
}
}
*pRcvNum = RcvNum;
return (1);
}
沁恒的芯片很有特色,质量也是很棒的 一扩8,确实不错啊。 沁恒芯片也是很棒的,支持国产芯片 很棒,很不错,真想st转沁恒 一扩8,牛X了。 这是串口扩展?太好了~
我们就是对串口需求多~~~ 好老的片子了,现在什么价了?好多年前用过。 这是老片子么?第一次知道串口扩展的片子~
页:
[1]