打印
[单片机芯片]

沁恒八串口扩展芯片CH438详解

[复制链接]
8821|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2021-10-1 19:21 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
 很多单片机,比如51单片机,只有一个或两个串口。所以,有时会遇到串口不够用的情况,这时候可以换一款串口更多的单片机。而有时你又不想换一款单片机,那可以使用本文要介绍的八扩展串口芯片CH438。芯片是沁恒的,沁恒的芯片用了挺多,很有特色,质量也是很棒的。二话不说,先上简介。





 CH438芯片的特色,在于单芯片有8个扩展串口,每个串口有128字节的FIFO,这可以节省你的单片机的RAM,同时,不容易因为没读取接收缓冲里的数据而使缓冲区溢出。CH438的访问接口是并行口,用的引脚比较多,数据脚和地址脚可共用。外围简单,只需要一个晶振。上电路图




使用特权

评论回复
沙发
tpgf|  楼主 | 2021-10-1 19:22 | 只看该作者
现在来上代码


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);
                }
        }
       
}


使用特权

评论回复
板凳
tpgf|  楼主 | 2021-10-1 19:22 | 只看该作者
初始化时先调用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 != '\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[UARTx];
       
        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);
}



使用特权

评论回复
地板
onlycook| | 2021-10-5 10:36 | 只看该作者
沁恒的芯片很有特色,质量也是很棒的

使用特权

评论回复
5
caigang13| | 2021-10-5 18:32 | 只看该作者
一扩8,确实不错啊。

使用特权

评论回复
6
海滨消消| | 2021-10-9 11:13 | 只看该作者
沁恒芯片也是很棒的,支持国产芯片

使用特权

评论回复
7
两只袜子| | 2021-10-11 10:22 | 只看该作者
很棒,很不错,真想st转沁恒

使用特权

评论回复
8
yangxiaor520| | 2021-10-14 07:43 | 只看该作者
一扩8,牛X了。

使用特权

评论回复
9
skyred| | 2021-10-15 14:21 | 只看该作者
这是串口扩展?太好了~
我们就是对串口需求多~~~

使用特权

评论回复
10
6552918| | 2021-10-15 14:50 | 只看该作者
好老的片子了,现在什么价了?好多年前用过。

使用特权

评论回复
11
sadicy| | 2021-10-16 14:41 | 只看该作者
这是老片子么?第一次知道串口扩展的片子~

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2028

主题

15903

帖子

13

粉丝