454|0

1679

帖子

0

资源

纯净的硅(高级)

沁恒八串口扩展芯片CH438详解 [复制链接]

很多单片机,比如51单片机,只有一个或两个串口。所以,有时会遇到串口不够用的情况,这时候可以换一款串口更多的单片机。而有时你又不想换一款单片机,那可以使用本文要介绍的八扩展串口芯片CH438。芯片是沁恒的,沁恒的芯片用了挺多,很有特色,质量也是很棒的。二话不说,先上简介。

image.png  

image.png  

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

image.png  

现在来上代码


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 != '\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);
}

 


回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

最新文章 更多>>
    关闭
    站长推荐上一条 1/6 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表