STM32的ch438串口扩展芯片l例程,注意到了8位数据口占用的PC其他位的端口不能接CH438Q的中断引脚,避免读写数据造成中断异常

基于STM32的ch438串口扩展芯片使用

似是燕归来 2019-06-22 18:52:25  8796  收藏 22
分类专栏: STM32 文章标签: CH438  STM32 串口扩展芯片
版权
CH438串口扩展芯片是一个一对八的串口扩展芯片,在一些串口需要过多的场合比较有用。这个串口芯片事实上并没有占用MCU的串口它实际上是使用了8个IO口做数据的传输。下面我就简单介绍一下怎么使用STM32驱动这个串口扩展芯片。并演示一个用CH438发送一段MODBUS码给电脑,电脑发给STM32的数据数据也回显示到电脑上.

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

实际的电路是这样的:

需要注意的几点就是: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博主「似是燕归来」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/s2014201506/article/details/93335353

热门文章

暂无图片
编程学习 ·

C语言二分查找详解

二分查找是一种知名度很高的查找算法&#xff0c;在对有序数列进行查找时效率远高于传统的顺序查找。 下面这张动图对比了二者的效率差距。 二分查找的基本思想就是通过把目标数和当前数列的中间数进行比较&#xff0c;从而确定目标数是在中间数的左边还是右边&#xff0c;将查…
暂无图片
编程学习 ·

GMX 命令分类列表

建模和计算操作命令&#xff1a; 1.1 . 创建拓扑与坐标文件 gmx editconf - 编辑模拟盒子以及写入子组(subgroups) gmx protonate - 结构质子化 gmx x2top - 根据坐标生成原始拓扑文件 gmx solvate - 体系溶剂化 gmx insert-molecules - 将分子插入已有空位 gmx genconf - 增加…
暂无图片
编程学习 ·

一文高效回顾研究生课程《数值分析》重点

数值分析这门课的本质就是用离散的已知点去估计整体&#xff0c;就是由黑盒子产生的结果去估计这个黑盒子。在数学里这个黑盒子就是一个函数嘛&#xff0c;这门课会介绍许多方法去利用离散点最大化地逼近这个函数&#xff0c;甚至它的导数、积分&#xff0c;甚至微分方程的解。…
暂无图片
编程学习 ·

在职阿里5年,一个28岁女软测工程师的心声

简单的先说一下&#xff0c;坐标杭州&#xff0c;14届本科毕业&#xff0c;算上年前在阿里巴巴的面试&#xff0c;一共有面试了有6家公司&#xff08;因为不想请假&#xff0c;因此只是每个晚上去其他公司面试&#xff0c;所以面试的公司比较少&#xff09; ​ 编辑切换为居中…
暂无图片
编程学习 ·

字符串左旋c语言

目录 题目&#xff1a; 解题思路&#xff1a; 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1a; 总代码&#xff1a; 题目&#xff1a; 实现一个函数&#xff0c;可以左旋字符串中的k个字符。 例如&#xff1a; ABCD左旋一个字符得到BCDA ABCD左旋两个字符…
暂无图片
编程学习 ·

设计模式--观察者模式笔记

模式的定义与特点 观察者&#xff08;Observer&#xff09;模式的定义&#xff1a;指多个对象间存在一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式&#xf…
暂无图片
编程学习 ·

睡觉突然身体动不了,什么是睡眠痽痪症

很多朋友可能有这样的体验&#xff0c;睡觉过程中突然意识清醒&#xff0c;身体却动弹不了。这时候感觉非常恐怖&#xff0c;希望旁边有一个人推自己一下。阳光以前也经常会碰到这样的情况&#xff0c;一年有一百多次&#xff0c;那时候很害怕晚上到来&#xff0c;睡觉了就会出…
暂无图片
编程学习 ·

深入理解C++智能指针——浅析MSVC源码

文章目录unique_ptrshared_ptr 与 weak_ptrstd::bad_weak_ptr 异常std::enable_shared_from_thisunique_ptr unique_ptr 是一个只移型别&#xff08;move-only type&#xff0c;只移型别还有std::mutex等&#xff09;。 结合一下工厂模式&#xff0c;看看其基本用法&#xff…
暂无图片
编程学习 ·

@TableField(exist = false)

TableField(exist false) //申明此字段不在数据库存在&#xff0c;但代码中需要用到它&#xff0c;通知Mybatis-plus在做写库操作是忽略它。,.
暂无图片
编程学习 ·

Java Web day15

第十二章文件上传和下载 一、如何实现文件上传 要实现Web开发中的文件上传功能&#xff0c;通常需要完成两步操作&#xff1a;一.是在Web页面中添加上传输入项&#xff1b;二是在Servlet中读取上传文件的数据&#xff0c;并保存到本地硬盘中。 需要使用一个Apache组织提供一个…
暂无图片
编程学习 ·

【51nod 2478】【单调栈】【前缀和】小b接水

小b接水题目解题思路Code51nod 2478 小b接水 题目 输入样例 12 0 1 0 2 1 0 1 3 2 1 2 1输出样例 6解题思路 可以发现最后能拦住水的都是向两边递减高度&#xff08;&#xff1f;&#xff09; 不管两个高积木之间的的积木是怎样乱七八糟的高度&#xff0c;最后能用来装水的…
暂无图片
编程学习 ·

花了大半天写了一个UVC扩展单元调试工具

基于DIRECTSHOW 实现的&#xff0c;用的是MFC VS2019. 详见&#xff1a;http://www.usbzh.com/article/detail-761.html 获取方法 加QQ群:952873936&#xff0c;然后在群文件\USB调试工具&测试软件\UVCXU-V1.0(UVC扩展单元调试工具-USB中文网官方版).exe USB中文网 USB中文…
暂无图片
编程学习 ·

贪心(一):区间问题、Huffman树

区间问题 例题一&#xff1a;区间选点 给定 N 个闭区间 [ai,bi]请你在数轴上选择尽量少的点&#xff0c;使得每个区间内至少包含一个选出的点。 输出选择的点的最小数量。 位于区间端点上的点也算作区间内。 输入格式 第一行包含整数 N&#xff0c;表示区间数。 接下来 …
暂无图片
编程学习 ·

C语言练习实例——费氏数列

目录 题目 解法 输出结果 题目 Fibonacci为1200年代的欧洲数学家&#xff0c;在他的着作中曾经提到&#xff1a;「若有一只免子每个月生一只小免子&#xff0c;一个月后小免子也开始生产。起初只有一只免子&#xff0c;一个月后就有两只免子&#xff0c;二个月后有三只免子…
暂无图片
编程学习 ·

Android开发(2): Android 资源

个人笔记整理 Android 资源 Android中的资源&#xff0c;一般分为两类&#xff1a; 系统内置资源&#xff1a;Android SDK中所提供的已经定义好的资源&#xff0c;用户可以直接拿来使用。 用户自定义资源&#xff1a;用户自己定义或引入的&#xff0c;只适用于当前应用的资源…
暂无图片
编程学习 ·

零基础如何在短时间内拿到算法offer

​算法工程师是利用算法处理事物的职业 算法&#xff08;Algorithm&#xff09;是一系列解决问题的清晰指令&#xff0c;也就是说&#xff0c;能够对一定规范的输入&#xff0c;在有限时间内获得所要求的输出。 如果一个算法有缺陷&#xff0c;或不适合于某个问题&#xff0c;执…
暂无图片
编程学习 ·

人工智能:知识图谱实战总结

人工智能python&#xff0c;NLP&#xff0c;知识图谱&#xff0c;机器学习&#xff0c;深度学习人工智能&#xff1a;知识图谱实战前言一、实体建模工具Protegepython&#xff0c;NLP&#xff0c;知识图谱&#xff0c;机器学习&#xff0c;深度学习 人工智能&#xff1a;知识图…
暂无图片
编程学习 ·

【无标题】

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…