精华内容
下载资源
问答
  • 此文件为 WK2114 UART 1 拓展 4的 驱动程序, 基于STM32F2 系列CPU,通过终端收发数据, 测试通过可用。
  • 最近在做一个智能垃圾桶的项目,小区用的那种不是家里面的那种哈,由于需要四个垃圾桶,所以挂载多个模组就是一个比较麻烦的事情,一般STM32的芯片最多就只有八个串口,所以选择拓展串口的方式来做。 主题 使用的是...

    引言

    最近在做一个智能垃圾桶的项目,小区用的那种不是家里面的那种哈,由于需要四个垃圾桶,所以挂载多个模组就是一个比较麻烦的事情,一般STM32的芯片最多就只有八个串口,所以选择拓展串口的方式来做。

    主题

    使用的是CH438Q串口拓展芯片,芯片是QFP44元引脚的封装,座板也比较好做,或者买一个 同样封装的芯片夹具也可以使用。这里贴一下原理图

    因为我这里用的是地址与数据复用模式所以A0          ~A6没用
    因为我这里用的是地址与数据复用模式所以A0~A6没用

    在这里插入图片描述
    这里要注意RST引脚是低电平复位,所以需要上拉 不要悬空

    代码部分

    我这里使用的是用IO口模拟 当然你也可以用FSMC去做

    代码思路

    CH438_Init();        //初始化你的引脚
    CH438_ResetSeril(5); //复位你的串口
    CH438_Uart_Init(5,4800); //配置你的串口
    OK进入主题
    
    #include "CH485.h"
    #include "delay.h"
    #include "usart.h"
      #include "stm32f4xx_hal_eth.h"
    #include "string.h"
    	#include "sys.h"
    #define Fpclk    	    1843200//666600       /* 定义内部时钟频率,默认外部晶振的12分频    */
    #define MaxRecvLen    50         	  /* 接收缓冲区大小    */
    #define CH438_CONL_PORT    GPIOB
    #define CH438_DATA_PORT    GPIOB
    #define CH438_DATA_PORT1    GPIO
    #define CH438_DATA_PIN     ((uint16_t)0x00FF)	    //数据地址引脚  PB0-7
    
    
    const unsigned char offsetadd[] = {0x00,0x10,0x20,0x30,0x08,0x18,0x28,0x38,};		/* 串口号的偏移地址 */
    const unsigned char Interruptnum[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,};	/* SSR寄存器中断号对应值 */
     
    unsigned char Revbuff[MaxRecvLen];		/* 接收缓存区 */
    unsigned char RevLen;					/* 接收计数 */
     
    void SetOutPut(uint16_t GPIO_Pin)  //IO输出模式
    {
    	GPIO_InitTypeDef CH438_gpio;
    	
    	CH438_gpio.Pin   = GPIO_Pin;
    	CH438_gpio.Speed = GPIO_SPEED_HIGH;
    	CH438_gpio.Mode  = GPIO_MODE_OUTPUT_PP;	//推挽输出
    	HAL_GPIO_Init(CH438_DATA_PORT, &CH438_gpio);
     
    }
    void SetInPut(uint16_t GPIO_Pin)//IO输入模式
    {
    	GPIO_InitTypeDef CH438_gpio;
    	
    	CH438_gpio.Pin   = GPIO_Pin;
    	CH438_gpio.Speed = GPIO_SPEED_HIGH;
    	CH438_gpio.Mode  = GPIO_MODE_INPUT;		//上拉输入
    	HAL_GPIO_Init(CH438_DATA_PORT, &CH438_gpio);
    }
    void CH438_Init() //IO口中断等初始化
    {
      	GPIO_InitTypeDef GPIO_InitStructure;
    
       __HAL_RCC_GPIOB_CLK_ENABLE();           //开启GPIOB时钟
    	 __HAL_RCC_GPIOD_CLK_ENABLE();           //开启GPIOB时钟
    
    	GPIO_InitStructure.Mode  = GPIO_MODE_OUTPUT_PP;
    	GPIO_InitStructure.Pin   = 0X00FF;
    	GPIO_InitStructure.Speed = GPIO_SPEED_MEDIUM;
    	HAL_GPIO_Init(CH438_DATA_PORT,&GPIO_InitStructure);
    	
    	
    	GPIO_InitStructure.Pin  = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
    	HAL_GPIO_Init(GPIOD,&GPIO_InitStructure);
    	
    	GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;	
    	GPIO_InitStructure.Pin  = GPIO_PIN_2;
    	HAL_GPIO_Init(GPIOD,&GPIO_InitStructure);
    	
    	HAL_NVIC_SetPriority(EXTI2_IRQn,2,1);       //抢占优先级为2,子优先级为1
      HAL_NVIC_EnableIRQ(EXTI2_IRQn);             //使能中断线2
    
        AMOD = 1;
     
    }
     
    //中断服务函数
    void EXTI2_IRQHandler(void)
    {
        HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);//调用中断处理公用函数
    }
    //中断服务程序中需要做的事情
    //在HAL库中所有的外部中断服务函数都会调用此函数
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    {
        if(GPIO_Pin == GPIO_PIN_2)
    		{
    			u8 gInterruptStatus;
    			u8 InterruptStatus;
    			u8 i;
    		
    					gInterruptStatus = CH438ReadReg( REG_SSR_ADDR );
    					//printf("\r\nSSR: %02x\r\n",gInterruptStatus );
    					if(!gInterruptStatus)
    					{ 
    						__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    						return ;
    					}				
    						for(i=0; i<8; i++)
    					{
    						if( gInterruptStatus & Interruptnum[i] )    /* 检测哪个串口发生中断 */
    						{
    							InterruptStatus = CH438ReadReg( offsetadd[i] | REG_IIR_ADDR ) & 0x0f;    /* 读串口的中断状态 */	
    								//printf("\r\nInterruptStatus: %02x\r\n",InterruptStatus );
    							switch( InterruptStatus )
    							{
    								case INT_NOINT:			/* 没有中断 */					
    									break;
    								case INT_THR_EMPTY:		/* THR空中断 */						
    									break;
    								case INT_RCV_OVERTIME:	/* 接收超时中断 */
    								
    									RevLen = CH438_RecvDatas(i, Revbuff);					
    									CH438_SendDatas(i, Revbuff, RevLen);
    									
    								printf("USART:%d ->",i);
    								 printf("DATA:%s\r\n",Revbuff );
    								 memset(Revbuff,0,RevLen);
    									break;
    								case INT_RCV_SUCCESS:	/* 接收数据可用中断 */
    									RevLen = CH438_RecvDatas(i, Revbuff);
    									CH438_SendDatas(i, Revbuff, RevLen);
    									break;
    								case INT_RCV_LINES:		/* 接收线路状态中断 */
    									CH438ReadReg( offsetadd[i] | REG_LSR_ADDR );
    									break;
    								case INT_MODEM_CHANGE:	/* MODEM输入变化中断 */
    									CH438ReadReg( offsetadd[i] | REG_MSR_ADDR );
    									break;
    								default:
    									break;
    		 
    							}
    						}
    					}
    												
    		}
    	
    }
    void CH438WriteReg(u8 add,u8 data)  //写一个字节到寄存器
    {
    	
    	//CH438_DATA_PORT->ODR = (CH438_DATA_PORT->ODR&0XFF00);
    
    	CS = 1;
    	WR = 1;
    	RD = 1;
    	SetOutPut(CH438_DATA_PIN);
    	CH438_DATA_PORT->ODR = (CH438_DATA_PORT->ODR&0XFF00)|add; //低八位十数据位确保高八位数据不变  写寄存器地址 
    	CS = 0;
    	ALE =1;
    	delay_us(1);
    	ALE = 0;
    	
    	CH438_DATA_PORT->ODR = (CH438_DATA_PORT->ODR&0XFF00)|data; //写数据
    	WR =0 ;
    	delay_us(1);
    	WR =1;
    	CS =1;
    }
     
     
    u8 CH438ReadReg(u8 add) //读取一个字节
    {
    	u8 value;
    	
    	CS = 1;
    	WR =1;
    	RD =1;
    	SetOutPut(CH438_DATA_PIN);   //
    	CS = 0;
    	ALE =1;
    
    	CH438_DATA_PORT->ODR = (CH438_DATA_PORT->ODR&0XFF00)|add;
    	ALE = 0;
    	SetInPut(CH438_DATA_PIN);
    	RD = 0;
    	value = (uint8_t)CH438_DATA_PORT->IDR;
    	
     
    	RD =1;
    	CS =1;
    	//printf("value: %02x\r\n",value);
    	return value;
    }
     
    unsigned char CH438_CheckIIR(unsigned char num)
    {
    	unsigned char value;
    	
    	value = CH438ReadReg( offsetadd[num] | REG_IIR_ADDR );
    	return value;
    }
    void CH438_CloseSeril(unsigned char num) //关闭某位串口
    {
    	CH438WriteReg(offsetadd[num]|REG_IER_ADDR, BIT_IER_LOWPOWER);
    }
     
    void CH438_CloseALLSeril(void) //关闭所有串口
    {
    	CH438WriteReg(offsetadd[0]|REG_IER_ADDR, BIT_IER_LOWPOWER|BIT_IER_SLP);
    }
    void CH438_ResetSeril(unsigned char num) //复位串口
    {
    	CH438WriteReg(offsetadd[num]|REG_IER_ADDR, BIT_IER_RESET);
    }
    void CH438_SetBandrate(unsigned char num, unsigned long value)//设置波特率 未使用此函数
    {
    
    	uint16_t bandspeed;
    	
    	bandspeed = Fpclk/16/value;
      CH438WriteReg(offsetadd[num]|REG_LCR_ADDR, BIT_LCR_DLAB );  
    	CH438WriteReg(offsetadd[num]|REG_DLL_ADDR, (uint8_t)bandspeed);
    	CH438WriteReg(offsetadd[num]|REG_DLM_ADDR, (uint8_t)(bandspeed>>8));
    	
     
    	printf("bandrate: %d\r\n", bandspeed);
    	printf("DLM: %d\r\n", CH438ReadReg(offsetadd[num]|REG_DLM_ADDR));
    	printf("DLL: %d\r\n", CH438ReadReg(offsetadd[num]|REG_DLL_ADDR));
     
    }
    void CH438_UARTInit(unsigned char num)//初始化  未使用到
    {
    	CH438_SetBandrate(num, 9600);	/* CH438串口1波特率设置 */
    	CH438_TranConfig(num); 			/* CH438串口1数据格式配置及FIFO大小 */	
    }
    //发送数据
     
    void CH438_SendDatas(unsigned char num, unsigned char* sendbuff,unsigned char len)
    {
    
    	while(len)
    	{		
    		if((CH438ReadReg(offsetadd[num]|REG_LSR_ADDR)&BIT_LSR_TEMT))	    //LSR->THRE==1  保持寄存器空
    		{
    			CH438WriteReg(offsetadd[num]|REG_THR_ADDR, *sendbuff++);
    			len--;
    		}
    	}
    	
    }
    //接收数据
     
    unsigned char CH438_RecvDatas(unsigned char num, unsigned char* revbuff)
    {
    	uint8_t len=0;
    	uint8_t *p_rev;
    	
    	p_rev = revbuff;
     
    	while( ( CH438ReadReg( offsetadd[num]|REG_LSR_ADDR ) & BIT_LSR_DATARDY ) == 0 );    /*等待数据准备好 */
    	while((CH438ReadReg(offsetadd[num]|REG_LSR_ADDR)&BIT_LSR_DATARDY))	//LSR->DATARDY==1
    	{
    		*p_rev = CH438ReadReg(offsetadd[num]|REG_RBR_ADDR);
    		p_rev++;
    		len++;
    	}
    	return len;
    }
    void CH438_TranConfig(unsigned char num)
    {	
    	/* 发送数据格式:8位数据,无校验,1个停止位  */
    	CH438WriteReg(offsetadd[num]|REG_LCR_ADDR, BIT_LCR_WORDSZ1 | BIT_LCR_WORDSZ0);
    	/* 设置FIFO模式,触发点为112字节 */
    	CH438WriteReg(offsetadd[num]|REG_FCR_ADDR, BIT_FCR_RECVTG1 | BIT_FCR_RECVTG0 | BIT_FCR_FIFOEN);	
    	CH438WriteReg(offsetadd[num]|REG_FCR_ADDR,CH438ReadReg(offsetadd[num]|REG_FCR_ADDR)| BIT_FCR_TFIFORST|BIT_FCR_RFIFORST);
    }
     
    void CH438_INTConfig(unsigned char num)
    {	
    	/* 注意: CH438打开BIT_IER_IETHRE中断(0->1),会产生一个发生空中断 */	
    	CH438WriteReg(offsetadd[num]|REG_IER_ADDR,BIT_IER_IERECV );
    	CH438_CheckIIR(num);
    	CH438WriteReg(offsetadd[num]|REG_MCR_ADDR, BIT_MCR_OUT2);//    | BIT_MCR_RTS     | BIT_MCR_DTR);//可以产生一个实际的中断	
    }
     
    void CH438_AutoHFCtrl(unsigned char num)
    {
        CH438WriteReg( offsetadd[num]|REG_MCR_ADDR, BIT_MCR_AFE | BIT_MCR_OUT2 | BIT_MCR_RTS );/* 设置MCR寄存器的AFE和RTS为1 */
    }
    
    void CH438_RegTEST(unsigned char num)//测试使用的函数
    {
     
    	printf("current test serilnum:  %02x \r\n",(unsigned short)offsetadd[num]);
    	printf("IER: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_IER_ADDR));//?IER
    	printf("IIR: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_IIR_ADDR));//?IIR
    	printf("LCR: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_LCR_ADDR));//?LCR
    	printf("MCR: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_MCR_ADDR));//?MCR
    	printf("LSR: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_LSR_ADDR));//?LSR
    	printf("MSR: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_MSR_ADDR));//?MSR
    //	CH438WriteReg(offsetadd[num] | REG_SCR_ADDR, 0x78);
    	printf("SCR: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_SCR_ADDR));//?SCR
    	printf("FCR: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_FCR_ADDR));//?SCR
    	//printf("SSR: %02x\r\n",(unsigned short)CH438ReadReg( offsetadd[num] | REG_SSR_ADDR ));//?SCR
    }
    //串口初始化函数 输入参数 串口号和波特率
    void CH438_Uart_Init(unsigned char num,unsigned long value)
    {
     
    	uint8_t dlab=0;
    	uint16_t bandspeed;
    	dlab = CH438ReadReg(offsetadd[num]|REG_IER_ADDR);
    	dlab &= 0xDF;
    	CH438WriteReg(offsetadd[num]|REG_IER_ADDR, dlab);
    	
    	dlab = CH438ReadReg(offsetadd[num]|REG_LCR_ADDR);
    	dlab |= 0x80;		//置LCR寄存器DLAB位为1
    	CH438WriteReg(offsetadd[num]|REG_LCR_ADDR, dlab);
    	
    	bandspeed = Fpclk/16/value;
    	CH438WriteReg(offsetadd[num]|REG_DLL_ADDR, (uint8_t)bandspeed);
    	CH438WriteReg(offsetadd[num]|REG_DLM_ADDR, (uint8_t)(bandspeed>>8));
    	dlab &= 0x7F;		//置IIR寄存器DLAB位为0
    	CH438WriteReg(offsetadd[num]|REG_LCR_ADDR, dlab);
    	CH438WriteReg(offsetadd[num]|REG_FCR_ADDR,BIT_FCR_RECVTG1 | BIT_FCR_RECVTG0 | BIT_FCR_FIFOEN );
    	CH438WriteReg(offsetadd[num]|REG_LCR_ADDR,BIT_LCR_WORDSZ1 | BIT_LCR_WORDSZ0 );
    	//CH438WriteReg(offsetadd[num]|REG_IER_ADDR,BIT_IER_IELINES | BIT_IER_IETHRE | BIT_IER_IERECV);
    	//CH438WriteReg(offsetadd[num]|REG_MCR_ADDR,BIT_MCR_OUT2    | BIT_MCR_RTS     | BIT_MCR_DTR);
    	CH438WriteReg(offsetadd[num]|REG_FCR_ADDR,CH438ReadReg(offsetadd[num]|REG_FCR_ADDR)| BIT_FCR_TFIFORST|BIT_FCR_RFIFORST);
     //CH438_TranConfig(num);
    	CH438_INTConfig(num);
    }
    

    自己要注意看官方的文档来选择打开什么中断、我开始遇到问题为什么每次发送都进入中断,因为在初始化的时候开启了发送完成中断,如果初始化的时候只打开了接受中断、那么只有当接受的时候才会触发一次中断,然后我们进入中断去读取IIR寄存器去判断中断类型

    #ifndef _CH485_H
    #define _CH485_H
    #include "sys.h"
    #include "delay.h"
    #define REG_RBR_ADDR        0x00      /* 串口0接收缓冲寄存器地址 */
    #define REG_THR_ADDR        0x00      /* 串口0发送保持寄存器地址 */
    #define REG_IER_ADDR        0x01      /* 串口0中断使能寄存器地址 */
    #define REG_IIR_ADDR        0x02      /* 串口0中断识别寄存器地址 */
    #define REG_FCR_ADDR        0x02      /* 串口0FIFO控制寄存器地址 */
    #define REG_LCR_ADDR        0x03      /* 串口0线路控制寄存器地址 */
    #define REG_MCR_ADDR        0x04      /* 串口0MODEM控制寄存器地址 */
    #define REG_LSR_ADDR        0x05      /* 串口0线路状态寄存器地址 */
    #define REG_MSR_ADDR        0x06      /* 串口0MODEM状态寄存器地址 */
    #define REG_SCR_ADDR        0x07      /* 串口0用户可定义寄存器地址 */
    #define REG_DLL_ADDR        0x00      /* 波特率除数锁存器低8位字节地址 */
    #define REG_DLM_ADDR        0x01      /* 波特率除数锁存器高8位字节地址 */
     
    /* CH438内部串口0~7 专用状态寄存器 */
     
    #define REG_SSR_ADDR        0x4F       /* 专用状态寄存器地址 */
     
     
    /* IER寄存器的位 */
     
    #define BIT_IER_RESET       0x80      /* 该位置1则软复位该串口 */
    #define BIT_IER_LOWPOWER    0x40      /* 该位为1则关闭该串口的内部基准时钟 */
    #define BIT_IER_SLP         0x20      /* 串口0是SLP,为1则关闭时钟震荡器 */
    #define BIT_IER1_CK2X       0x20      /* 串口1是CK2X,为1则强制将外部时钟信号2倍频后作为内部基准时钟 */
    #define BIT_IER_IEMODEM     0x08      /* 该位为1允许MODEM输入状态变化中断 */
    #define BIT_IER_IELINES     0x04      /* 该位为1允许接收线路状态中断 */
    #define BIT_IER_IETHRE      0x02      /* 该位为1允许发送保持寄存器空中断 */
    #define BIT_IER_IERECV      0x01      /* 该位为1允许接收到数据中断 */
     
    /* IIR寄存器的位 */
     
    #define BIT_IIR_FIFOENS1    0x80
    #define BIT_IIR_FIFOENS0    0x40      /* 该2位为1表示起用FIFO */
     
    /* 中断类型:0001没有中断,0110接收线路状态中断,0100接收数据可用中断,1100接收数据超时中断,0010THR寄存器空中断,0000MODEM输入变化中断 */
    #define BIT_IIR_IID3        0x08
    #define BIT_IIR_IID2        0x04	//接受数据可用
    #define BIT_IIR_IID1        0x02	//THR寄存器空中断
    #define BIT_IIR_NOINT       0x01
     
    /* FCR寄存器的位 */
     
    /* 触发点: 00对应1个字节,01对应16个字节,10对应64个字节,11对应112个字节 */
    #define BIT_FCR_RECVTG1     0x80      /* 设置FIFO的中断和自动硬件流控制的触发点 */
    #define BIT_FCR_RECVTG0     0x40      /* 设置FIFO的中断和自动硬件流控制的触发点 */
     
    #define BIT_FCR_TFIFORST    0x04      /* 该位置1则清空发送FIFO中的数据 */
    #define BIT_FCR_RFIFORST    0x02      /* 该位置1则清空接收FIFO中的数据 */
    #define BIT_FCR_FIFOEN      0x01      /* 该位置1则起用FIFO,为0则禁用FIFO */
     
    /* LCR寄存器的位 */
     
    #define BIT_LCR_DLAB        0x80      /* 为1才能存取DLL,DLM,为0才能存取RBR/THR/IER */
    #define BIT_LCR_BREAKEN     0x40      /* 为1则强制产生BREAK线路间隔*/
     
    /* 设置校验格式:当PAREN为1时,00奇校验,01偶校验,10标志位(MARK,置1),11空白位(SPACE,清0) */
    #define BIT_LCR_PARMODE1    0x20      /* 设置奇偶校验位格式 */
    #define BIT_LCR_PARMODE0    0x10      /* 设置奇偶校验位格式 */
     
    #define BIT_LCR_PAREN       0x08      /* 为1则允许发送时产生和接收校验奇偶校验位 */
    #define BIT_LCR_STOPBIT     0x04      /* 为1则两个停止位,为0一个停止位 */
     
    /* 设置字长度:00则5个数据位,01则6个数据位,10则7个数据位,11则8个数据位 */
    #define BIT_LCR_WORDSZ1     0x02      /* 设置字长长度 */
    #define BIT_LCR_WORDSZ0     0x01
     
    /* MCR寄存器的位 */
     
    #define BIT_MCR_AFE         0x20      /* 为1允许CTS和RTS硬件自动流控制 */
    #define BIT_MCR_LOOP        0x10      /* 为1使能内部回路的测试模式 */
    #define BIT_MCR_OUT2        0x08      /* 为1允许该串口的中断请求输出 */
    #define BIT_MCR_OUT1        0x04      /* 为用户定义的MODEM控制位 */
    #define BIT_MCR_RTS         0x02      /* 该位为1则RTS引脚输出有效 */
    #define BIT_MCR_DTR         0x01      /* 该位为1则DTR引脚输出有效 */
     
    /* LSR寄存器的位 */
     
    #define BIT_LSR_RFIFOERR    0x80      /* 为1表示在接收FIFO中存在至少一个错误 */
    #define BIT_LSR_TEMT        0x40      /* 为1表示THR和TSR全空 */
    #define BIT_LSR_THRE        0x20      /* 为1表示THR空*/
    #define BIT_LSR_BREAKINT    0x10      /* 该位为1表示检测到BREAK线路间隔 */
    #define BIT_LSR_FRAMEERR    0x08      /* 该位为1表示读取数据帧错误 */
    #define BIT_LSR_PARERR      0x04      /* 该位为1表示奇偶校验错误 */
    #define BIT_LSR_OVERR       0x02      /* 为1表示接收FIFO缓冲区溢出 */
    #define BIT_LSR_DATARDY     0x01      /* 该位为1表示接收FIFO中有接收到的数据 */
     
    /* MSR寄存器的位 */
     
    #define BIT_MSR_DCD         0x80      /* 该位为1表示DCD引脚有效 */
    #define BIT_MSR_RI          0x40      /* 该位为1表示RI引脚有效 */
    #define BIT_MSR_DSR         0x20      /* 该位为1表示DSR引脚有效 */
    #define BIT_MSR_CTS         0x10      /* 该位为1表示CTS引脚有效 */
    #define BIT_MSR_DDCD        0x08      /* 该位为1表示DCD引脚输入状态发生变化过 */
    #define BIT_MSR_TERI        0x04      /* 该位为1表示RI引脚输入状态发生变化过 */
    #define BIT_MSR_DDSR        0x02      /* 该位为1表示DSR引脚输入状态发生变化过 */
    #define BIT_MSR_DCTS        0x01      /* 该位为1表示CTS引脚输入状态发生变化过 */
     
    /* 中断状态码 */
     
    #define INT_NOINT           0x01      /* 没有中断 */
    #define INT_THR_EMPTY       0x02      /* THR空中断 */
    #define INT_RCV_OVERTIME    0x0C      /* 接收超时中断 */
    #define INT_RCV_SUCCESS     0x04      /* 接收数据可用中断 */
    #define INT_RCV_LINES       0x06      /* 接收线路状态中断 */
    #define INT_MODEM_CHANGE    0x00      /* MODEM输入变化中断 */
     
    #define CH438_IIR_FIFOS_ENABLED 0xC0  /* 起用FIFO */
     
     
    #define WR   PDout(3)
    #define ALE  PDout(7)
    #define RD   PDout(4)
    #define CS   PDout(5)
    #define AMOD PDout(6)
    #define INT  PDout(1)
    void SetOutPut(uint16_t GPIO_Pin);  //IO输出模式
    void SetInPut(uint16_t GPIO_Pin);
    void CH438_Init(void);
    void CH438WriteReg(u8 add,u8 data);
    u8 CH438ReadReg(u8 add);
    unsigned char CH438_CheckIIR(unsigned char num);
    void CH438_CloseSeril(unsigned char num);
    void CH438_CloseALLSeril(void);
    void CH438_ResetSeril(unsigned char num);
    void CH438_SetBandrate(unsigned char num, unsigned long value);
    void CH438_UARTInit(unsigned char num);
    void CH438_SendDatas(unsigned char num, unsigned char* sendbuff,unsigned char len);
    unsigned char CH438_RecvDatas(unsigned char num, unsigned char* revbuff);
    void CH438_TranConfig(unsigned char num);
    void CH438_INTConfig(unsigned char num);
    void CH438_AutoHFCtrl(unsigned char num);
    void CH438_RegTEST(unsigned char num);
    void CH438_Uart_Init(unsigned char num,unsigned long value);
    #endif
    

    效果图

    在这里插入图片描述
    遇到问题自己多看文档
    附上我的工程
    https://download.csdn.net/download/qq_36369488/11762005

    展开全文
  • HI2108 USB转4串口芯片手册及资料。 LQFP64封装,替代CP2108等 HI2108是一款 USB 转 4 串口控制芯片,提供 4 组全双工的异步串口 UART1/2/3/4...HI2108非常适合于Linux工控服务器/树莓派主板等串口/RS232/RS485拓展
  • SPI扩展4串口芯片

    2018-12-07 15:47:07
    通过SPI扩展串口,简单实用,适合在嵌入式平台中,芯片资源较少但又不想改设计方案时使用
  • 串口扩展芯片

    千次阅读 2020-06-24 14:50:51
    串口扩展芯片 WK2124 实现SPI桥接/扩展4个增强功能串口(UART)功能。扩展的子通道具备以下功能特点: 每个子通道UART的波特率、字长、校验格式可以独立设置,最高可以提供2Mbps的通道速率; 每个子通道可以独立...

    串口扩展芯片

    WK2124

    实现SPI桥接/扩展4个增强功能串口(UART)功能。扩展的子通道具备以下功能特点:

    1. 每个子通道UART的波特率、字长、校验格式可以独立设置,最高可以提供2Mbps的通道速率;
    2. 每个子通道可以独立设置工作在IrDA红外通信;
    3. 每个子通道具备收/发独立的256 BYTE FIFO,FIFO的中断可按用户需求进行编程触发点;

    封装:SSOP20
    工作电压:2.5~5.0V
    具备自动休眠/唤醒功能

    原理框图

    在这里插入图片描述

    封装引脚图

    在这里插入图片描述

    与控制器接口

    在这里插入图片描述

    1. SPI总线:WK2124通过SPI和MCU进行数据通信。SPI会传输命令字节和数据字节。
    2. 中断:WK2124的IRQ连接到MCU的外部中断输入引脚。这个连接非必须,未连接时只能通过查询的编程方式实现对子串口的数据收发,效率较低;
    3. 复位控制:低电平有效,时间长度为10ms。复位以后,所有寄存器值恢复到默认值,SPI总线上的命令解析同时复位;
    4. 时钟电路:采用无源晶振,晶振大小和子串口波特率相关;晶振必须并联的匹配电阻是1M欧姆;
    展开全文
  • 串口拓展

    2015-12-15 10:02:00
    今天桌子下面找出一个破电路板看到一颗芯片GM8125,这个芯片主要功能就是拓展串口。 GM8125可以将一个全双工的标准串口扩展成5个标准串口,并能通过外部引脚控制串口扩展模式:单通道工作模式和多通道工作模式,即...

        今天桌子下面找出一个破电路板看到一颗芯片GM8125,这个芯片主要功能就是拓展串口。

    GM8125可以将一个全双工的标准串口扩展成5个标准串口,并能通过外部引脚控制串口扩展模式:单通道工作模式和多通道工作模式,即可以指定一个子串口和母串口以相同的波特率单一的工作,也可以让所有子串口在母串口波特率基础上分频同时工作。 
    该芯片工作在多通道模式下时,子串口能主动响应从机发送的数据,并由母串口发送给主机,同时返回子串口地址。该模式使每个从机的发送要求都能被及时地响应,即使所有从机同时有发送要求,数据也不会丢失,基本实现了主控单元和外设通讯的实时性。 
    该芯片母串口和子串口的工作波特率可由软件调节,而不需要修改外部电路和晶振频率。 该芯片的外部控制少,应用灵活,编程使用简单,适用于大多数有串口扩展需求的系统。

     

    2 特征 
    ——采用写控制字的方式对芯片进行控制 ——各子串口波特率可调(统一调节) ——数据格式10位或11位可选 
    ——单通道模式下,最高波特率支持20Mbps;多通道模式下,子串口最高波特率38400bps ——子串口数:5个 
    ——由一个引脚选择芯片的工作方式是单通道工作模式还是多通道工作模式 
    ——在单通道工作模式下,芯片工作无需初始化设置,工作串口由地址线控制选择 ——在多通道工作模式下,各子串口的波特率等于母串口波特率的6分频 ——在多通道工作模式下,接收时地址线SRADD2~0向MCU返回接收子通道的地址,MCU
    接收到母串口送来的数据后就可根据SRADD2~0状态判断数据是从哪一个子串口送来的;发送时先由MCU选择子串口再向母串口发送数据 ——与标准串口通讯格式兼容,TTL电平输出 ——宽工作电压:2.3~6.7V 
    ——输出波特率误差小于0.2%,输入波特率误差要求小于2.8% ——每bit采样16次,提高数据正确性 
    ——输入地址引脚有50~80KΩ Pull-Down电阻,其它输入引脚有50~80KΩ Pull-Up电
    阻(OSCI除外)

     

    http://wenku.baidu.com/link?url=tZA4CIYvXRKGOv5uUi9mz0Tv5zxjeZzwmZqHjlSYmEo---GntQSE1jnNKBrQNerrveH1G9Yv_w9Tf0GKM0L0iLyL3l05U3qMxQdNi8ErXTy

    转载于:https://www.cnblogs.com/yygsj/p/5047261.html

    展开全文
  • HI2108是一款 USB 转 4 串口控制芯片,提供 4 组全双工的异步串口 UART1/2/3/4,用于为计算机扩展异步串口,或者将普通的串口设备升级到 USB 总线。HI2108非常适合于Linux工控服务器/树莓派主板等串口/RS232/RS485...
  • 基于STM32的ch438串口扩展芯片使用

    万次阅读 热门讨论 2019-06-22 18:52:25
    CH438串口扩展芯片是一个一对八的串口扩展芯片,在一些串口需要过多的场合比较有用。这个串口芯片事实上并没有占用MCU的串口它实际上是使用了8个IO口做数据的传输。下面我就简单介绍一下怎么使用STM32驱动这个串口...

    CH438串口扩展芯片是一个一对八的串口扩展芯片,在一些串口需要过多的场合比较有用。这个串口芯片事实上并没有占用MCU的串口它实际上是使用了8个IO口做数据的传输。下面我就简单介绍一下怎么使用STM32驱动这个串口扩展芯片。并演示一个用CH438发送一段MODBUS码给电脑,电脑发给STM32的数据数据也回显示到电脑上.

    CH438我用的是44管脚的LQFP44封装。

    54。还有

    实际的电路是这样的:

     

    需要注意的几点就是:RXT代表的是复位应该接上拉电阻到电源,我用的是STM32的复位电路共用。这里不能悬空。

    晶振使用的是22.1184MHz晶振频率很高注意起振电容的选择。我采用的是20pf。

    D0~D7与STM32 的PC0~7连接,这八位是数据传输位,其他的几位都是控制位。本次接收数据使用到了本芯片和STM32的中断,INT叫对应的就是中断线。注意这个管脚不能连接到PC口上因为PC口已经当做数据口用了,如果连接到PC口高八位上,在芯片读写数据的时候出异常。

    下面这些是芯片内部的寄存器:主要就是配置他们。

    #ifndef _CH438_H
    #define _CH438_H
    #include "sys.h"
    #include "delay.h"
    #define REG_RBR_ADDR        0x00      /* 串口0接收缓冲寄存器地址 */
    #define REG_THR_ADDR        0x00      /* 串口0发送保持寄存器地址 */
    #define REG_IER_ADDR        0x01      /* 串口0中断使能寄存器地址 */
    #define REG_IIR_ADDR        0x02      /* 串口0中断识别寄存器地址 */
    #define REG_FCR_ADDR        0x02      /* 串口0FIFO控制寄存器地址 */
    #define REG_LCR_ADDR        0x03      /* 串口0线路控制寄存器地址 */
    #define REG_MCR_ADDR        0x04      /* 串口0MODEM控制寄存器地址 */
    #define REG_LSR_ADDR        0x05      /* 串口0线路状态寄存器地址 */
    #define REG_MSR_ADDR        0x06      /* 串口0MODEM状态寄存器地址 */
    #define REG_SCR_ADDR        0x07      /* 串口0用户可定义寄存器地址 */
    #define REG_DLL_ADDR        0x00      /* 波特率除数锁存器低8位字节地址 */
    #define REG_DLM_ADDR        0x01      /* 波特率除数锁存器高8位字节地址 */
    
    /* CH438内部串口0~7 专用状态寄存器 */
    
    #define REG_SSR_ADDR        0x4F       /* 专用状态寄存器地址 */
    
    
    /* IER寄存器的位 */
    
    #define BIT_IER_RESET       0x80      /* 该位置1则软复位该串口 */
    #define BIT_IER_LOWPOWER    0x40      /* 该位为1则关闭该串口的内部基准时钟 */
    #define BIT_IER_SLP         0x20      /* 串口0是SLP,为1则关闭时钟震荡器 */
    #define BIT_IER1_CK2X       0x20      /* 串口1是CK2X,为1则强制将外部时钟信号2倍频后作为内部基准时钟 */
    #define BIT_IER_IEMODEM     0x08      /* 该位为1允许MODEM输入状态变化中断 */
    #define BIT_IER_IELINES     0x04      /* 该位为1允许接收线路状态中断 */
    #define BIT_IER_IETHRE      0x02      /* 该位为1允许发送保持寄存器空中断 */
    #define BIT_IER_IERECV      0x01      /* 该位为1允许接收到数据中断 */
    
    /* IIR寄存器的位 */
    
    #define BIT_IIR_FIFOENS1    0x80
    #define BIT_IIR_FIFOENS0    0x40      /* 该2位为1表示起用FIFO */
    
    /* 中断类型:0001没有中断,0110接收线路状态中断,0100接收数据可用中断,1100接收数据超时中断,0010THR寄存器空中断,0000MODEM输入变化中断 */
    #define BIT_IIR_IID3        0x08
    #define BIT_IIR_IID2        0x04	//接受数据可用
    #define BIT_IIR_IID1        0x02	//THR寄存器空中断
    #define BIT_IIR_NOINT       0x01
    
    /* FCR寄存器的位 */
    
    /* 触发点: 00对应1个字节,01对应16个字节,10对应64个字节,11对应112个字节 */
    #define BIT_FCR_RECVTG1     0x80      /* 设置FIFO的中断和自动硬件流控制的触发点 */
    #define BIT_FCR_RECVTG0     0x40      /* 设置FIFO的中断和自动硬件流控制的触发点 */
    
    #define BIT_FCR_TFIFORST    0x04      /* 该位置1则清空发送FIFO中的数据 */
    #define BIT_FCR_RFIFORST    0x02      /* 该位置1则清空接收FIFO中的数据 */
    #define BIT_FCR_FIFOEN      0x01      /* 该位置1则起用FIFO,为0则禁用FIFO */
    
    /* LCR寄存器的位 */
    
    #define BIT_LCR_DLAB        0x80      /* 为1才能存取DLL,DLM,为0才能存取RBR/THR/IER */
    #define BIT_LCR_BREAKEN     0x40      /* 为1则强制产生BREAK线路间隔*/
    
    /* 设置校验格式:当PAREN为1时,00奇校验,01偶校验,10标志位(MARK,置1),11空白位(SPACE,清0) */
    #define BIT_LCR_PARMODE1    0x20      /* 设置奇偶校验位格式 */
    #define BIT_LCR_PARMODE0    0x10      /* 设置奇偶校验位格式 */
    
    #define BIT_LCR_PAREN       0x08      /* 为1则允许发送时产生和接收校验奇偶校验位 */
    #define BIT_LCR_STOPBIT     0x04      /* 为1则两个停止位,为0一个停止位 */
    
    /* 设置字长度:00则5个数据位,01则6个数据位,10则7个数据位,11则8个数据位 */
    #define BIT_LCR_WORDSZ1     0x02      /* 设置字长长度 */
    #define BIT_LCR_WORDSZ0     0x01
    
    /* MCR寄存器的位 */
    
    #define BIT_MCR_AFE         0x20      /* 为1允许CTS和RTS硬件自动流控制 */
    #define BIT_MCR_LOOP        0x10      /* 为1使能内部回路的测试模式 */
    #define BIT_MCR_OUT2        0x08      /* 为1允许该串口的中断请求输出 */
    #define BIT_MCR_OUT1        0x04      /* 为用户定义的MODEM控制位 */
    #define BIT_MCR_RTS         0x02      /* 该位为1则RTS引脚输出有效 */
    #define BIT_MCR_DTR         0x01      /* 该位为1则DTR引脚输出有效 */
    
    /* LSR寄存器的位 */
    
    #define BIT_LSR_RFIFOERR    0x80      /* 为1表示在接收FIFO中存在至少一个错误 */
    #define BIT_LSR_TEMT        0x40      /* 为1表示THR和TSR全空 */
    #define BIT_LSR_THRE        0x20      /* 为1表示THR空*/
    #define BIT_LSR_BREAKINT    0x10      /* 该位为1表示检测到BREAK线路间隔 */
    #define BIT_LSR_FRAMEERR    0x08      /* 该位为1表示读取数据帧错误 */
    #define BIT_LSR_PARERR      0x04      /* 该位为1表示奇偶校验错误 */
    #define BIT_LSR_OVERR       0x02      /* 为1表示接收FIFO缓冲区溢出 */
    #define BIT_LSR_DATARDY     0x01      /* 该位为1表示接收FIFO中有接收到的数据 */
    
    /* MSR寄存器的位 */
    
    #define BIT_MSR_DCD         0x80      /* 该位为1表示DCD引脚有效 */
    #define BIT_MSR_RI          0x40      /* 该位为1表示RI引脚有效 */
    #define BIT_MSR_DSR         0x20      /* 该位为1表示DSR引脚有效 */
    #define BIT_MSR_CTS         0x10      /* 该位为1表示CTS引脚有效 */
    #define BIT_MSR_DDCD        0x08      /* 该位为1表示DCD引脚输入状态发生变化过 */
    #define BIT_MSR_TERI        0x04      /* 该位为1表示RI引脚输入状态发生变化过 */
    #define BIT_MSR_DDSR        0x02      /* 该位为1表示DSR引脚输入状态发生变化过 */
    #define BIT_MSR_DCTS        0x01      /* 该位为1表示CTS引脚输入状态发生变化过 */
    
    /* 中断状态码 */
    
    #define INT_NOINT           0x01      /* 没有中断 */
    #define INT_THR_EMPTY       0x02      /* THR空中断 */
    #define INT_RCV_OVERTIME    0x0C      /* 接收超时中断 */
    #define INT_RCV_SUCCESS     0x04      /* 接收数据可用中断 */
    #define INT_RCV_LINES       0x06      /* 接收线路状态中断 */
    #define INT_MODEM_CHANGE    0x00      /* MODEM输入变化中断 */
    
    #define CH438_IIR_FIFOS_ENABLED 0xC0  /* 起用FIFO */
    
    
    #define WR   PDout(3)
    #define ALE  PDout(7)
    #define RD   PDout(4)
    #define CS   PDout(5)
    #define AMOD PDout(6)
    #define INT  PDout(1)
    void SetOutPut(void);
    void SetInPut(void);
    void CH438_Init(void);
    void CH438WriteReg(u8 add,u8 data);
    u8 CH438ReadReg(u8 add);
    unsigned char CH438_CheckIIR(unsigned char num);
    void CH438_CloseSeril(unsigned char num);
    void CH438_CloseALLSeril(void);
    void CH438_ResetSeril(unsigned char num);
    void CH438_SetBandrate(unsigned char num, unsigned long value);
    void CH438_UARTInit(unsigned char num);
    void CH438_SendDatas(unsigned char num, unsigned char* sendbuff,unsigned char len);
    unsigned char CH438_RecvDatas(unsigned char num, unsigned char* revbuff);
    void CH438_TranConfig(unsigned char num);
    void CH438_INTConfig(unsigned char num);
    void CH438_AutoHFCtrl(unsigned char num);
    void CH438_RegTEST(unsigned char num);
    void CH438_Uart_Init(unsigned char num,unsigned long value);
    #endif
    

    上面就是CH438.h头文件,以下就是main函数,本程序只打开了串口2

    
    int  main()
    {
    	u8 ssr =0 ;
            u8 AddCom[8] =	  {01,05,01,17,255,00,221,195};   	//增压
    
    	delay_init();	    	 
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2	  	
    	uart_init(9600);
    	LCD_Init();
    	CH438_Init();  
    	
    	CH438_ResetSeril(2);  //软件复位串口2
    	CH438_Uart_Init(2,9600); //串口2打开 波特率9600
    	delay_ms(100);
    	
    	while(1)
    	{
    		CH438_SendDatas(2,AddCom,8);
    		CH438_SendDatas(2,(u8*)"\r\n",2);
    		delay_ms(1000);	
    	}
    }

    下面是主要的函数

    #include "ch438.h"
    #include "delay.h"
    #include "usart.h"
    #include "lcd.h"
    #define Fpclk    	  1843200         /* 定义内部时钟频率,默认外部晶振的12分频    */
    #define MaxRecvLen    50         	  /* 接收缓冲区大小    */
    
    const unsigned char offsetadd[] = {0x00,0x10,0x20,0x30,0x08,0x18,0x28,0x38,};		/* 串口号的偏移地址 */
    const unsigned char Interruptnum[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,};	/* SSR寄存器中断号对应值 */
    
    unsigned char Revbuff[MaxRecvLen];		/* 接收缓存区 */
    unsigned char RevLen;					/* 接收计数 */
    
    
    
    
    void SetOutPut()  //IO输出模式
    {
    	GPIOC->CRL &=0;
    	GPIOC->CRL = 0X33333333;
    
    }
    void SetInPut()//IO输入模式
    {
    	GPIOC->CRL &=0;
    	GPIOC->CRL = 0X88888888;
    }
    void CH438_Init() //IO口中断等初始化
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    	EXTI_InitTypeDef EXTI_InitStructure;
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,ENABLE);
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    	
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    	GPIO_InitStructure.GPIO_Pin  = 0X00FF;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOC,&GPIO_InitStructure);
    	
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
    	GPIO_Init(GPIOD,&GPIO_InitStructure);
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_1;
    	GPIO_Init(GPIOD,&GPIO_InitStructure);
    	GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource1);
    	EXTI_InitStructure.EXTI_Line = EXTI_Line1;
    	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
    	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    	EXTI_Init(&EXTI_InitStructure);
    	
    	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    	NVIC_Init(&NVIC_InitStructure);
    	EXTI_ClearITPendingBit(EXTI_Line1);
    	AMOD = 1;
    
    }
    
    void CH438WriteReg(u8 add,u8 data)  //写一个字节到寄存器
    {
    	u16  value ;
    	CS = 1;
    	WR = 1;
    	RD = 1;
    	SetOutPut();
    	GPIOC->ODR = (GPIOC->ODR&0XFF00)|add; //低八位十数据位确保高八位数据不变  写寄存器地址 
    	CS = 0;
    	ALE =1;
    	delay_us(1);
    	ALE = 0;
    	
    	GPIOC->ODR = (GPIOC->ODR&0XFF00)|data; //写数据
    	WR =0 ;
    	delay_us(1);
    	WR =1;
    	CS =1;
    }
    
    
    u8 CH438ReadReg(u8 add) //读取一个字节
    {
    	u8 value;
    	u8 value1;
    	CS = 1;
    	WR =1;
    	RD =1;
    	SetOutPut();   //
    	CS = 0;
    	ALE =1;
    	GPIOC->ODR = (GPIOC->ODR&0XFF00)|add;
    	ALE = 0;
    	SetInPut();
    	RD = 0;
    	value = GPIO_ReadInputData(GPIOC);
    	
    
    	RD =1;
    	CS =1;
    	
    	return value;
    }
    
    unsigned char CH438_CheckIIR(unsigned char num)
    {
    	unsigned char value;
    	
    	value = CH438ReadReg( offsetadd[num] | REG_IIR_ADDR );
    	return value;
    }
    void CH438_CloseSeril(unsigned char num) //关闭某位串口
    {
    	CH438WriteReg(offsetadd[num]|REG_IER_ADDR, BIT_IER_LOWPOWER);
    }
    
    void CH438_CloseALLSeril(void) //关闭所有串口
    {
    	CH438WriteReg(offsetadd[0]|REG_IER_ADDR, BIT_IER_LOWPOWER|BIT_IER_SLP);
    }
    void CH438_ResetSeril(unsigned char num) //复位串口
    {
    	CH438WriteReg(offsetadd[num]|REG_IER_ADDR, BIT_IER_RESET);
    }
    void CH438_SetBandrate(unsigned char num, unsigned long value)//设置波特率 未使用此函数
    {
    	uint8_t dlab=0;
    	uint16_t bandspeed;
    	
    	
    	bandspeed = Fpclk/16/value;
            CH438WriteReg(offsetadd[num]|REG_LCR_ADDR, BIT_LCR_DLAB );  
    	CH438WriteReg(offsetadd[num]|REG_DLL_ADDR, (uint8_t)bandspeed);
    	CH438WriteReg(offsetadd[num]|REG_DLM_ADDR, (uint8_t)(bandspeed>>8));
    	
    
    	printf("bandrate: %d\n", bandspeed);
    	printf("DLM: %d\n", CH438ReadReg(offsetadd[num]|REG_DLM_ADDR));
    	printf("DLL: %d\n", CH438ReadReg(offsetadd[num]|REG_DLL_ADDR));
    
    }
    void CH438_UARTInit(unsigned char num)//初始化  未使用到
    {
    	CH438_SetBandrate(num, 9600);	/* CH438串口1波特率设置 */
    	CH438_TranConfig(num); 			/* CH438串口1数据格式配置及FIFO大小 */	
    }
    //发送数据
    
    void CH438_SendDatas(unsigned char num, unsigned char* sendbuff,unsigned char len)
    {
    	
    	do
    	{
    		while((CH438ReadReg(offsetadd[num]|REG_LSR_ADDR)&BIT_LSR_THRE)==0);    //LSR->THRE==1  保持寄存器空
    		
    			CH438WriteReg(offsetadd[num]|REG_THR_ADDR,*sendbuff++);	
    	}while(--len);
    	
    }
    //接收数据
    
    unsigned char CH438_RecvDatas(unsigned char num, unsigned char* revbuff)
    {
    	uint8_t len=0;
    	uint8_t *p_rev;
    	
    	p_rev = revbuff;
    
    	while( ( CH438ReadReg( offsetadd[num]|REG_LSR_ADDR ) & BIT_LSR_DATARDY ) == 0 );    /*等待数据准备好 */
    	while((CH438ReadReg(offsetadd[num]|REG_LSR_ADDR)&BIT_LSR_DATARDY))	//LSR->DATARDY==1
    	{
    		*p_rev = CH438ReadReg(offsetadd[num]|REG_RBR_ADDR);
    		p_rev++;
    		len++;
    	}
    	return len;
    }
    void CH438_TranConfig(unsigned char num)
    {	
    	/* 发送数据格式:8位数据,无校验,1个停止位  */
    	CH438WriteReg(offsetadd[num]|REG_LCR_ADDR, BIT_LCR_WORDSZ1 | BIT_LCR_WORDSZ0);
    	/* 设置FIFO模式,触发点为112字节 */
    	CH438WriteReg(offsetadd[num]|REG_FCR_ADDR, BIT_FCR_RECVTG1 | BIT_FCR_RECVTG0 | BIT_FCR_FIFOEN);	
    	CH438WriteReg(offsetadd[num]|REG_FCR_ADDR,CH438ReadReg(offsetadd[num]|REG_FCR_ADDR)| BIT_FCR_TFIFORST|BIT_FCR_RFIFORST);
    }
    
    void CH438_INTConfig(unsigned char num)
    {	
    	/* 注意: CH438打开BIT_IER_IETHRE中断(0->1),会产生一个发生空中断 */	
    	CH438WriteReg(offsetadd[num]|REG_IER_ADDR, BIT_IER_IELINES | BIT_IER_IETHRE | BIT_IER_IERECV );
    	CH438_CheckIIR(num);
    	CH438WriteReg(offsetadd[num]|REG_MCR_ADDR, BIT_MCR_OUT2    | BIT_MCR_RTS     | BIT_MCR_DTR);//可以产生一个实际的中断	
    }
    
    void CH438_AutoHFCtrl(unsigned char num)
    {
        CH438WriteReg( offsetadd[num]|REG_MCR_ADDR, BIT_MCR_AFE | BIT_MCR_OUT2 | BIT_MCR_RTS );/* 设置MCR寄存器的AFE和RTS为1 */
    }
    //中断处理函数
    
    void EXTI1_IRQHandler()
    {
    	u8 gInterruptStatus;
    	u8 InterruptStatus;
    	u8 i;
    	static u8 j ;
    	if(EXTI_GetITStatus(EXTI_Line1)!= RESET)
    	{
    			gInterruptStatus = CH438ReadReg( REG_SSR_ADDR );
    			
    			if(!gInterruptStatus)
    			{ 
    				EXTI_ClearITPendingBit(EXTI_Line1);
    				return ;
    			}
    			
    			
    				for(i=0; i<8; i++)
    			{
    				if( gInterruptStatus & Interruptnum[i] )    /* 检测哪个串口发生中断 */
    				{
    					InterruptStatus = CH438ReadReg( offsetadd[i] | REG_IIR_ADDR ) & 0x0f;    /* 读串口的中断状态 */	
    					
    					switch( InterruptStatus )
    					{
    						case INT_NOINT:			/* 没有中断 */					
    							break;
    						case INT_THR_EMPTY:		/* THR空中断 */						
    							break;
    						case INT_RCV_OVERTIME:	/* 接收超时中断 */
    							RevLen = CH438_RecvDatas(i, Revbuff);					
    							CH438_SendDatas(i, Revbuff, RevLen);
    							break;
    						case INT_RCV_SUCCESS:	/* 接收数据可用中断 */
    							RevLen = CH438_RecvDatas(i, Revbuff);
    							CH438_SendDatas(i, Revbuff, RevLen);
    							break;
    						case INT_RCV_LINES:		/* 接收线路状态中断 */
    							CH438ReadReg( offsetadd[i] | REG_LSR_ADDR );
    							break;
    						case INT_MODEM_CHANGE:	/* MODEM输入变化中断 */
    							CH438ReadReg( offsetadd[i] | REG_MSR_ADDR );
    							break;
    						default:
    							break;
    
    					}
    				}
    			}
    	
    		EXTI_ClearITPendingBit(EXTI_Line1);
    	}
    }
    void CH438_RegTEST(unsigned char num)//测试使用的函数
    {
    
    	printf("current test serilnum: %d \r\n",(unsigned short)offsetadd[num]);
    	printf("IER: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_IER_ADDR));//?IER
    	printf("IIR: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_IIR_ADDR));//?IIR
    	printf("LCR: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_LCR_ADDR));//?LCR
    	printf("MCR: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_MCR_ADDR));//?MCR
    	printf("LSR: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_LSR_ADDR));//?LSR
    	printf("MSR: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_MSR_ADDR));//?MSR
    	//CH438WriteReg(offsetadd[num] | REG_SCR_ADDR, 0x78);
    	printf("SCR: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_SCR_ADDR));//?SCR
    	printf("FCR: %02x\r\n",(unsigned short)CH438ReadReg(offsetadd[num] | REG_FCR_ADDR));//?SCR
    
    }
    //串口初始化函数 输入参数 串口号和波特率
    void CH438_Uart_Init(unsigned char num,unsigned long value)
    {
    
    	uint8_t dlab=0;
    	uint16_t bandspeed;
    	dlab = CH438ReadReg(offsetadd[num]|REG_IER_ADDR);
    	dlab &= 0xDF;
    	CH438WriteReg(offsetadd[num]|REG_IER_ADDR, dlab);
    	
    	dlab = CH438ReadReg(offsetadd[num]|REG_LCR_ADDR);
    	dlab |= 0x80;		//置LCR寄存器DLAB位为1
    	CH438WriteReg(offsetadd[num]|REG_LCR_ADDR, dlab);
    	
    	bandspeed = Fpclk/16/value;
    	CH438WriteReg(offsetadd[num]|REG_DLL_ADDR, (uint8_t)bandspeed);
    	CH438WriteReg(offsetadd[num]|REG_DLM_ADDR, (uint8_t)(bandspeed>>8));
    	dlab &= 0x7F;		//置IIR寄存器DLAB位为0
    	CH438WriteReg(offsetadd[num]|REG_LCR_ADDR, dlab);
    	CH438WriteReg(offsetadd[num]|REG_FCR_ADDR,BIT_FCR_RECVTG1 | BIT_FCR_RECVTG0 | BIT_FCR_FIFOEN );
    	CH438WriteReg(offsetadd[num]|REG_LCR_ADDR,BIT_LCR_WORDSZ1 | BIT_LCR_WORDSZ0 );
    	CH438WriteReg(offsetadd[num]|REG_IER_ADDR,BIT_IER_IELINES | BIT_IER_IETHRE | BIT_IER_IERECV);
    	CH438WriteReg(offsetadd[num]|REG_MCR_ADDR,BIT_MCR_OUT2    | BIT_MCR_RTS     | BIT_MCR_DTR);
    	CH438WriteReg(offsetadd[num]|REG_FCR_ADDR,CH438ReadReg(offsetadd[num]|REG_FCR_ADDR)| BIT_FCR_TFIFORST|BIT_FCR_RFIFORST);
    
    
    }
    

     

    实验结果如下:

     

    垃圾CSDN

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • USB转串口芯片:CH340

    万次阅读 2017-06-26 10:01:52
    最新推荐:免晶振(CH340E/C/B)和超小体积(CH340E) ... CH340是一个USB 总线的转接芯片,实现USB转串口或者USB转打印口。... 在串口方式下,CH340提供常用的MODEM联络信号,用于为计算机扩展异步串
  • 本驱动程序基于wk2166串口扩展芯片,实现了spi转串口的linux驱动程序的设计。本驱动源代码在为开微电子的网站也能找到源码。。
  • EU104是具有5个UART接口的数据转发芯片,可实现将1个UART扩展为4个UART接口,主接口通讯速率最高460800bps,子接口通讯速率最高38400bps,各接口通讯速率可由软件独立设置,包括数据位、校验位、停止位等,可适应绝...
  • WK系列串口扩展芯片详解(含电路例程)  很多单片机,比如51单片机,只有一个或两个串口。所以,有时会遇到串口不够用的情况,这时候可以换一款串口更多的单片机。而有时你又不想换一款单片机,那可以使用本文要介绍...
  • 串口扩展芯片,支持UART/IIC/SPI/并行总线接口,可扩展4路串口。硬件简单,电源种类单一。串口设计简单易操作。
  • GM8125串口拓展应用

    千次阅读 2012-07-03 19:54:43
    在远程抄表的设计中因串口资源不足,使用了GM8125串口拓展的解决方案,功能类似于某公司生产的多路232、485拓展卡。 GM8125最大的特点就是收发数据互不干扰,波特率、数据长度可设置, 可以将一个全双工的标准串口...
  • 非常全的源程序。包括小灯,数码管等基本的操作还有像时钟芯片,液晶,串口,DA,AD等源程序。
  • SJXXX串口扩展芯片 UART(1) to UART(4)

    千次阅读 2017-07-17 16:18:12
    SJXX串口扩展芯片 1 概述 SJ000是一款具备I2C总线/SPI总线/UART接口的四通道异步收发器件,通过模式选择使得该器件工作于以上任何一种主接口模式下。器件的四个通道UART可提供高达2Mbps的数据率,低功耗模式和睡眠...
  • 可以通过模式选择使得该芯片工作于以上任何一种主接口模式,将选 定的主接口扩展为4个增强功能的UART。 扩展的子通道的UART具备如下功能特点: 1.每个子通道UART的波特率、字长、校验格式可以独立设置,最高可以提供...
  • 外接一个同步移位寄存器 74LS165芯片拓展一个 8 位 并行输入端口的电路, 可将接在74LS165芯片的8个开关 S0——S7 的状态 通过 串行口方式 0 读到 单片机内。 SH/LD : (一) 控制端 低电平: 74LS165芯片可以...
  • F28335第十二篇——串口拓展(XR16C854)

    千次阅读 2019-12-16 22:27:27
    本文介绍一种串口拓展方法。硬件上基于DSP28335和XR16C854。 硬件设计 XR
  • 串行口方式0拓展并行输出端口 02 74LS164 一、实验目的 二、实验内容 三、实验步骤 四、C代码如下 五、实验结果 六、实验体会 一、实验目的 74HC164、74HCT164 是 8 位边沿触发式移位寄存器,串行输入数据,...
  • 1、先讲解74LS164 移位芯片: 74HC164、74HCT164 是 8 位边沿触发式移位寄存器,串行输入数据,然后并行输出。 数据通过两个输入端(DSA 或 DSB)之一串行输入;任一输入端可以用作高电平使能端,控制另一输入端的...
  • 目标功能 实现温度的实时检测,并通过两个异步串口将数据发送至串口屏HMI和与蓝牙模块相连接的手机上。...STC15W4K48S4芯片 一块 HMI串口屏 一块 HC-05 蓝牙模块 一份 散件若干 软件 K...
  • I2C是一种较为常用的串行接口标准,具有协议完善、支持芯片较多和占用I/O线少等优点。I2C总线是PHILIPS公司为有效实现电子器件之间 的控制而开发的一种简单的双向两线总线。现在,I2C总线已经成为一个国际标准,在...
  • 接口的数据转发芯片,可通过 I2C 接口协议扩 展为 4 个标准的 UART 接口,UART 通讯速率最高 460800bps,各接口通讯参数可由软件独立设置, 包括通讯速率、数据位、校验位、停止位等,可 适应绝大部分串口设备的通讯...
  • CP2101芯片

    2021-03-16 14:43:14
    USB 转 UART 桥接器提供一个使用最小化的元件和PCB空间实现RS232 转USB 的简便的解决方案该芯片包含一个 USB 2.0 全速功能控制器USB收发器振荡器和带有全部的调制解调器控制信号的异步串行数据总线(UART)全部功能...
  • FPGA芯片行业科普

    千次阅读 2020-12-30 15:18:59
    ​ 文章大纲 中国FPGA芯片行业综述 ... •FPGA芯片特点及分类 ... •FPGA芯片行业产业链 ... •FPGA芯片关键技术 ... 中国FPGA芯片行业驱动因素 ... •5G通信体系建设提高FPGA芯片需求 ... 中国FPGA芯片行业制约...FPGA芯片...
  • 底层码农眼中的芯片

    2018-12-06 22:27:32
    底层码农眼中国内国际芯片行业的压子
  • WK2114是UART接口的4通道UART器件。WK2114将一个标准3线异步串口(UART)扩展成为4个增强 功能串口(UART)。主接口UART在数据传输时主接口的UART可以通过引脚配置为红外通信模式。 扩展的子通道的UART具备如下...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,207
精华内容 882
关键字:

拓展串口芯片