• 基于CAN的智能家居--代码


     

    systick_init();//初始化系统滴答定时器
    res_led_init();//初始化LED灯的IO口
    ori_key_init();//初始化KEY的IO口
    ch340_usart1_init(115200);//初始化USART1


    init_can1(21,11,4,2,0);//-----CAN总线通信速度:125K--16个Tq
    // //1+11+4----Tq分配规则

    timer_6_init();
    lcd_init();//初始化LCD屏
    at24c02_init();//初始化AT24C02
    touch_init();//初始化TOUCH屏
    gptm_tim12_ch2_output_pwm();



    rtc_init(rtc_dates);
    adc1_in4_init();

    ***************CAN**********************************

    /*
    函数功能:初始化CAN1
    函数形参:brp:分频器;tbs1:时间段1;tbs2:时间段2;tsjw:同步跳转;mode:模式
    */
    u8 init_can1(u8 brp, u8 tbs1, u8 tbs2, u8 tsjw, u8 mode)
    {
        u16 cnt=0;
    
        RCC->AHB1ENR|=1<<0;      //使能PORTA口时钟 
        
        GPIOA->MODER &= ~(3<<22);
        GPIOA->MODER |= (2<<22); //PA11 复用功能
        GPIOA->MODER &= ~(3<<24);
        GPIOA->MODER |= (2<<24); //PA12 复用功能 
        
        GPIOA->OTYPER &= ~(3 << 11);//类型  推挽
        
        GPIOA->OSPEEDR &= ~(0xf<< 22);//速度  50M
        GPIOA->OSPEEDR |= 0xa << 22;  
        
        GPIOA->AFR[1] &= ~(0XF << 12);
        GPIOA->AFR[1] |= 9 << 12;  //PA11  can1功能   AF9
        GPIOA->AFR[1] &= ~(0XF << 16);
        GPIOA->AFR[1] |= 9 << 16;  //PA12  can1功能   AF9
        
        
        RCC->APB1ENR |= 1<<25;//使能CAN1时钟 CAN1使用的是APB1的时钟(max:42M)
        
        CAN1->MCR = 0;        //退出睡眠模式(同时设置所有位为0)
        /*     
            非时间触发通信模式
            软件自动离线管理
            睡眠模式通过软件唤醒(清除CAN1->MCR的SLEEP位)
            报文不锁定,新的覆盖旧的,,
        */
        
        CAN1->MCR |= 1<<0;    //请求CAN进入初始化模式
        while ((CAN1->MSR & 1 << 0) == 0)
        {
            if (++cnt > 100)
            {
                return 2;    //进入初始化模式失败----超时监测
            }
        }
        
        CAN1->MCR |= 1<<4;    //禁止报文自动重发
        
        CAN1->BTR = 0;    //清除原来的设置.
        CAN1->BTR |= mode<<30;    //模式设置 0,普通模式;1,回环模式;
        CAN1->BTR |= (tsjw - 1) << 24;     //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位
        CAN1->BTR |= (tbs2 - 1) << 20;     //Tbs2=tbs2+1个时间单位
        CAN1->BTR |= (tbs1 - 1) << 16;    //Tbs1=tbs1+1个时间单位
        CAN1->BTR |= (brp - 1) ;      //分频系数(Fdiv)为brp+1
                                    //波特率:Fpclk1/((Tbs1+Tbs2+1)*Fdiv)
        
        CAN1->MCR &= ~(1<<0);        //请求CAN退出初始化模式
        while ((CAN1->MSR & 1<<0) == 1)
        {
            if (++cnt > 0XFFF0)
            {
                return 3;//退出初始化模式失败
            }
        }
        
        //过滤器初始化
        CAN1->FMR |= 1<<0;        //过滤器组工作在初始化模式
        CAN1->FA1R &= ~(1<<0);    //过滤器0先关闭
        
        CAN1->FS1R |= 1<<0;         //过滤器位宽为32位.
        CAN1->FM1R &= ~1;            //过滤器0工作在标识符屏蔽位模式
        
        CAN1->FFA1R &= ~1;        //过滤器0关联到FIFO_0
        
        CAN1->sFilterRegister[0].FR1 = 0;//32位ID
        CAN1->sFilterRegister[0].FR2 = 0;//32位MASK
        
        CAN1->FA1R |= 1<<0;        //激活过滤器0
        CAN1->FMR &= ~1;            //过滤器组进入正常模式
    
        return 0;
    }   
    u8 init_can1(u8 brp, u8 tbs1, u8 tbs2, u8 tsjw, u8 mode)
    u8 can1_tx_msg(u32 id,u8 ide,u8 rtr,u8 len, u8 *p_dat)
    {       
        u8 mbox;
        
        if (CAN1->TSR & (1<<26))
        {
            mbox=0;            //邮箱0为空
        }
        else if (CAN1->TSR & (1<<27))
        {
            mbox=1;            //邮箱1为空
        }
        else if (CAN1->TSR & (1<<28))
        {
            mbox=2;            //邮箱2为空
        }
        else 
        {
            return 0XFF;    //无空邮箱,无法发送 
        }
        
        CAN1->sTxMailBox[mbox].TIR = 0;        //清除之前的设置
        if (ide == 0)    //标准帧
        {
            id &= 0x7ff;//取低11位stdid
            id <<= 21;          
        }
        else        //扩展帧
        {
            id &= 0X1FFFFFFF;//取低32位extid
            id <<= 3;                                       
        }
        CAN1->sTxMailBox[mbox].TIR |= id;         
        CAN1->sTxMailBox[mbox].TIR |= ide << 2;      
        CAN1->sTxMailBox[mbox].TIR |= rtr << 1;
        
        len &= 0X0F;//得到低四位
        CAN1->sTxMailBox[mbox].TDTR &= ~(0XF);
        CAN1->sTxMailBox[mbox].TDTR |= len;       //设置DLC.
            
        CAN1->sTxMailBox[mbox].TDLR = 0;
        CAN1->sTxMailBox[mbox].TDHR = 0;
        //待发送数据存入邮箱.
        switch(len)
        {
            case 8:CAN1->sTxMailBox[mbox].TDHR |= (p_dat[7] << 24);
            case 7:CAN1->sTxMailBox[mbox].TDHR |= (p_dat[6] << 16);
            case 6:CAN1->sTxMailBox[mbox].TDHR |= (p_dat[5] <<  8);
            case 5:CAN1->sTxMailBox[mbox].TDHR |= (p_dat[4] <<  0);
            case 4:CAN1->sTxMailBox[mbox].TDLR |= (p_dat[3] << 24);
            case 3:CAN1->sTxMailBox[mbox].TDLR |= (p_dat[2] << 16);
            case 2:CAN1->sTxMailBox[mbox].TDLR |= (p_dat[1] <<  8);
            case 1:CAN1->sTxMailBox[mbox].TDLR |= (p_dat[0] <<  0);break;
            default: break;
        }
        
        CAN1->sTxMailBox[mbox].TIR |= 1; //请求发送邮箱数据  TXRQ
        
        return mbox;
    }
    can1_tx_msg(u32 id,u8 ide,u8 rtr,u8 len, u8 *p_dat)
    //获得发送状态.
    //mbox:邮箱编号;
    //返回值:发送状态. 0,挂起;0X05,发送失败;0X07,发送成功.
    u8 can1_tx_status(u8 mbox)
    {    
        u8 sta = 0;
        
        switch (mbox)
        {
            case 0: 
                sta |= CAN1->TSR & (1<<0);            //RQCP0
                sta |= CAN1->TSR & (1<<1);            //TXOK0
                sta |= (CAN1->TSR & (1<<26)) >> 24;    //TME0
                break;
            
            case 1: 
                sta |= CAN1->TSR & (1<<8) >> 8;        //RQCP1
                sta |= CAN1->TSR & (1<<9) >> 8;        //TXOK1
                sta |= (CAN1->TSR & (1<<27)) >> 25;    //TME1       
                break;
            
            case 2: 
                sta |= CAN1->TSR & (1<<16) >> 16;        //RQCP2
                sta |= CAN1->TSR & (1<<17) >> 16;        //TXOK2
                sta |= (CAN1->TSR & (1<<28)) >> 26;    //TME2
                break;
            
            default:
                sta = 0X05;//邮箱号不对,肯定失败.
                break;
        }
        return sta;
    } 
    //得到在FIFO0/FIFO1中接收到的报文个数.
    //fifox:0/1.FIFO编号;
    //返回值:FIFO0/FIFO1中的报文个数.
    u8 can1_fifo_status(u8 fifox)
    {
        if (fifox == 0)
        {
            return CAN1->RF0R & 0x03;
        }        
        else if (fifox == 1)
        {
            return CAN1->RF1R & 0x03; 
        }
        else 
        {
            return 0;
        }
    }
    
    //接收数据
    void can1_rx_msg(u32 *id,u8 *ide,u8 *rtr,u8 *len,u8 *p_dat,u8 fifox)
    {
        *ide = CAN1->sFIFOMailBox[fifox].RIR & 0x04;//得到标识符选择位的值  
         if(*ide == 0)//标准标识符
        {
            *id = CAN1->sFIFOMailBox[fifox].RIR >> 21;
        }
        else       //扩展标识符
        {
            *id = CAN1->sFIFOMailBox[fifox].RIR >> 3;
        }
        
        *rtr = CAN1->sFIFOMailBox[fifox].RIR & 0x02;    //得到远程发送请求值.
        *len = CAN1->sFIFOMailBox[fifox].RDTR & 0x0F;    //得到DLC
    
        //读取数据
        switch(*len)
        {
            case 8:p_dat[7] = ((CAN1->sFIFOMailBox[fifox].RDHR & 0xff000000) >> 24);
            case 7:p_dat[6] = ((CAN1->sFIFOMailBox[fifox].RDHR & 0x00ff0000) >> 16);
            case 6:p_dat[5] = ((CAN1->sFIFOMailBox[fifox].RDHR & 0x0000ff00) >>  8);
            case 5:p_dat[4] = ((CAN1->sFIFOMailBox[fifox].RDHR & 0x000000ff) >>  0);
            case 4:p_dat[3] = ((CAN1->sFIFOMailBox[fifox].RDLR & 0xff000000) >> 24);
            case 3:p_dat[2] = ((CAN1->sFIFOMailBox[fifox].RDLR & 0x00ff0000) >> 16);
            case 2:p_dat[1] = ((CAN1->sFIFOMailBox[fifox].RDLR & 0x0000ff00) >>  8);
            case 1:p_dat[0] = ((CAN1->sFIFOMailBox[fifox].RDLR & 0x000000ff) >>  0);break;
            default: break;    
        }
    
        fifox ? (CAN1->RF1R |= 0X20) : (CAN1->RF0R |= 0X20);//释放FIFOx邮箱
    }
    can1_tx_status、、 can1_fifo_status、、 can1_rx_msg
    //can发送一组数据(固定格式:ID为0Xaa,标准帧,数据帧)    
    //len:数据长度(最大为8)                     
    //msg:数据指针,最大为8个字节.
    //返回值:0,成功;
    //         其他,失败;
    u8 can1_send_msg(u8* msg, u8 len,u16 id)
    {    
        u8 mbox;
        u16 i=0;     
        
        mbox = can1_tx_msg(id,0,0,len,msg);
        
        while ((can1_tx_status(mbox) != 0X07))//等待发送结束
        {
            if(++i >= 0XFFF)
            {
                return 1;//发送失败?
            }
        }
        return 0;    //发送成功;
    }
    
    
    //can口接收数据查询
    //buf:数据缓存区;     
    //返回值:0,无数据被收到;
    //         其他,接收的数据长度;
    u8 can1_receive_msg(u8 *buf)
    {                      
        u32 id;
        u8 ide,rtr = 0,len=0; 
        
        if(can1_fifo_status(0) == 0)
        {
            return 0;    //没有接收到数据,直接退出      
        }
          can1_rx_msg(&id,&ide,&rtr,&len,buf, 0);     //读取数据
    
        if (rtr == 1)
        {
            len = 1;
        }
        return len;    
    }
    can1_receive_msg、、can1_send_msg

    ***************CAN**********************************

    *
    函数功能:初始化LCD显示控制器
    函数形参:无
    函数返回值:无
    备注:移植厂商给的示例
    */
    void lcd_init(void)
    {
        lcd_port_init();
        
        systick_delay_ms(120);//120ms
        
        LCD_ILI9486_CMD(0XF2);
        LCD_ILI9486_INDEX(0x18);
        LCD_ILI9486_INDEX(0xA3);
        LCD_ILI9486_INDEX(0x12);
        LCD_ILI9486_INDEX(0x02);
        LCD_ILI9486_INDEX(0XB2);
        LCD_ILI9486_INDEX(0x12);
        LCD_ILI9486_INDEX(0xFF);
        LCD_ILI9486_INDEX(0x10);
        LCD_ILI9486_INDEX(0x00);
        LCD_ILI9486_CMD(0XF8);
        LCD_ILI9486_INDEX(0x21);
        LCD_ILI9486_INDEX(0x04);
        LCD_ILI9486_CMD(0XF9);
        LCD_ILI9486_INDEX(0x00);
        LCD_ILI9486_INDEX(0x08);
        LCD_ILI9486_CMD(0x36);
        LCD_ILI9486_INDEX(0x08);   //设置RGB,含排线的屏
    //    LCD_ILI9486_INDEX(0x00);   //设置RGB,不含排线的屏
        LCD_ILI9486_CMD(0x3A);
        LCD_ILI9486_INDEX(0x05);   //设置16位BPP
        LCD_ILI9486_CMD(0xB4);
        LCD_ILI9486_INDEX(0x01);//0x00
        LCD_ILI9486_CMD(0xB6);
        LCD_ILI9486_INDEX(0x02);
        LCD_ILI9486_INDEX(0x22);
        LCD_ILI9486_CMD(0xC1);
        LCD_ILI9486_INDEX(0x41);
        LCD_ILI9486_CMD(0xC5);
        LCD_ILI9486_INDEX(0x00);
        LCD_ILI9486_INDEX(0x07);//0X18
        LCD_ILI9486_CMD(0xE0);
        LCD_ILI9486_INDEX(0x0F);
        LCD_ILI9486_INDEX(0x1F);
        LCD_ILI9486_INDEX(0x1C);
        LCD_ILI9486_INDEX(0x0C);
        LCD_ILI9486_INDEX(0x0F);
        LCD_ILI9486_INDEX(0x08);
        LCD_ILI9486_INDEX(0x48);
        LCD_ILI9486_INDEX(0x98);
        LCD_ILI9486_INDEX(0x37);
        LCD_ILI9486_INDEX(0x0A);
        LCD_ILI9486_INDEX(0x13);
        LCD_ILI9486_INDEX(0x04);
        LCD_ILI9486_INDEX(0x11);
        LCD_ILI9486_INDEX(0x0D);
        LCD_ILI9486_INDEX(0x00);
        LCD_ILI9486_CMD(0xE1);
        LCD_ILI9486_INDEX(0x0F);
        LCD_ILI9486_INDEX(0x32);
        LCD_ILI9486_INDEX(0x2E);
        LCD_ILI9486_INDEX(0x0B);
        LCD_ILI9486_INDEX(0x0D);
        LCD_ILI9486_INDEX(0x05);
        LCD_ILI9486_INDEX(0x47);
        LCD_ILI9486_INDEX(0x75);
        LCD_ILI9486_INDEX(0x37);
        LCD_ILI9486_INDEX(0x06);
        LCD_ILI9486_INDEX(0x10);
        LCD_ILI9486_INDEX(0x03);
        LCD_ILI9486_INDEX(0x24);
        LCD_ILI9486_INDEX(0x20);
        LCD_ILI9486_INDEX(0x00);
        
        LCD_ILI9486_CMD(0x11); 
        systick_delay_n_us(120000);//120ms 
        LCD_ILI9486_CMD(0x29);
        
        Lcd_Clear(0XFFFF);
        
        GPIOB->ODR |= (0X1 << 15);//开启背光
    }
    void lcd_init(void)
    /*
    函数功能:初始化LCD的IO口
    函数形参:无
    函数返回值:无
    备注:BL--PB15
        DB0--PD14    DB1--PD15    DB2--PD0    DB3--PD1    DB4--PE7
        DB5--PE8    DB6--PE9    DB7--PE10    DB8--PE11    DB9--PE12
        DB10--PE13    DB11--PE14    DB12--PE15    DB13--PD8    DB14--PD9
        DB15--PD10    CS--PG12    D/C--PF12    RD--PD4        WR--PD5
    
    */
    void lcd_port_init(void)
    {
        RCC->AHB1ENR |= (0X1 << 1);//PB
        RCC->AHB1ENR |= (0X1 << 3);//PD
        RCC->AHB1ENR |= (0X1 << 4);//PE
        RCC->AHB1ENR |= (0X1 << 5);//PF
        RCC->AHB1ENR |= (0X1 << 6);//PG
        
        GPIOE->MODER &= 0X00003FFF;//清空配置
        GPIOE->MODER |= 0X55554000;//配置为普通输出
        GPIOE->OTYPER &= 0X7F;//配置为推挽类型
        GPIOE->OSPEEDR |= 0XFFFFE000;//100MHz
        GPIOE->PUPDR &= 0X00003FFF;//无上下拉
        
        GPIOD->MODER &= 0X0FC0F0F0;
        GPIOD->MODER |= 0X50150505;
        GPIOD->OTYPER &= 0X38CC;
        GPIOD->OSPEEDR |= 0XF03F0F0F;
        GPIOD->PUPDR &= 0X0FC0F0F0;
        GPIOD->ODR |= (0X1 << 4);//RD始终为高
        
        GPIOB->MODER &= ~(0X3 << 30);
        GPIOB->MODER |=  (0X1 << 30);
        GPIOB->OTYPER &= ~(0X1 << 15);
        GPIOB->OSPEEDR |= (0X3 << 30);
        GPIOB->PUPDR &= ~(0X3 << 30);
        GPIOB->ODR &= ~(0X1 << 15);
        
        GPIOF->MODER &= ~(0X3 << 24);
        GPIOF->MODER |=  (0X1 << 24);
        GPIOF->OTYPER &= ~(0X1 << 12);
        GPIOF->OSPEEDR |= (0X3 << 24);
        GPIOF->PUPDR &= ~(0X3 << 24);
        GPIOF->ODR |= (0X1 << 12);
        
        GPIOG->MODER &= ~(0X3 << 24);
        GPIOG->MODER |=  (0X1 << 24);
        GPIOG->OTYPER &= ~(0X1 << 12);
        GPIOG->OSPEEDR |= (0X3 << 24);
        GPIOG->PUPDR &= ~(0X3 << 24);
        GPIOG->ODR |= (0X1 << 12);
    }
    
    /*
    函数功能:写入命令到LCD显示控制器
    函数形参:命令的值
    函数返回值:无
    备注:无
    
    
    */
    void LCD_ILI9486_CMD(u16 cmd)
    {
        CS = 0;
        DC = 0;
        WR = 0;
        if(cmd & 0x0001) GPIOD->BSRRL |= (0X1 << 14); else GPIOD->BSRRH |= (0X1 << 14);
        if(cmd & 0x0002) GPIOD->BSRRL |= (0X1 << 15); else GPIOD->BSRRH |= (0X1 << 15);
        if(cmd & 0x0004) GPIOD->BSRRL |= (0X1 <<  0); else GPIOD->BSRRH |= (0X1 <<  0);
        if(cmd & 0x0008) GPIOD->BSRRL |= (0X1 <<  1); else GPIOD->BSRRH |= (0X1 <<  1);
        if(cmd & 0x0010) GPIOE->BSRRL |= (0X1 <<  7); else GPIOE->BSRRH |= (0X1 <<  7);
        if(cmd & 0x0020) GPIOE->BSRRL |= (0X1 <<  8); else GPIOE->BSRRH |= (0X1 <<  8);
        if(cmd & 0x0040) GPIOE->BSRRL |= (0X1 <<  9); else GPIOE->BSRRH |= (0X1 <<  9);
        if(cmd & 0x0080) GPIOE->BSRRL |= (0X1 << 10); else GPIOE->BSRRH |= (0X1 << 10);
        if(cmd & 0x0100) GPIOE->BSRRL |= (0X1 << 11); else GPIOE->BSRRH |= (0X1 << 11);
        if(cmd & 0x0200) GPIOE->BSRRL |= (0X1 << 12); else GPIOE->BSRRH |= (0X1 << 12);
        if(cmd & 0x0400) GPIOE->BSRRL |= (0X1 << 13); else GPIOE->BSRRH |= (0X1 << 13);
        if(cmd & 0x0800) GPIOE->BSRRL |= (0X1 << 14); else GPIOE->BSRRH |= (0X1 << 14);
        if(cmd & 0x1000) GPIOE->BSRRL |= (0X1 << 15); else GPIOE->BSRRH |= (0X1 << 15);
        if(cmd & 0x2000) GPIOD->BSRRL |= (0X1 <<  8); else GPIOD->BSRRH |= (0X1 <<  8);
        if(cmd & 0x4000) GPIOD->BSRRL |= (0X1 <<  9); else GPIOD->BSRRH |= (0X1 <<  9);
        if(cmd & 0x8000) GPIOD->BSRRL |= (0X1 << 10); else GPIOD->BSRRH |= (0X1 << 10);
        WR = 1;
        CS = 1;
    }
    /*
    函数功能:写入参数到LCD显示控制器
    函数形参:命令的值
    函数返回值:无
    备注:无
    作者:李工
    时间:2018-09-03
    */
    void LCD_ILI9486_INDEX(u16 parameter)
    {
        CS = 0;
        DC = 1;
        WR = 0;
        if(parameter & 0x0001) GPIOD->BSRRL |= (0X1 << 14); else GPIOD->BSRRH |= (0X1 << 14);
        if(parameter & 0x0002) GPIOD->BSRRL |= (0X1 << 15); else GPIOD->BSRRH |= (0X1 << 15);
        if(parameter & 0x0004) GPIOD->BSRRL |= (0X1 <<  0); else GPIOD->BSRRH |= (0X1 <<  0);
        if(parameter & 0x0008) GPIOD->BSRRL |= (0X1 <<  1); else GPIOD->BSRRH |= (0X1 <<  1);
        if(parameter & 0x0010) GPIOE->BSRRL |= (0X1 <<  7); else GPIOE->BSRRH |= (0X1 <<  7);
        if(parameter & 0x0020) GPIOE->BSRRL |= (0X1 <<  8); else GPIOE->BSRRH |= (0X1 <<  8);
        if(parameter & 0x0040) GPIOE->BSRRL |= (0X1 <<  9); else GPIOE->BSRRH |= (0X1 <<  9);
        if(parameter & 0x0080) GPIOE->BSRRL |= (0X1 << 10); else GPIOE->BSRRH |= (0X1 << 10);
        if(parameter & 0x0100) GPIOE->BSRRL |= (0X1 << 11); else GPIOE->BSRRH |= (0X1 << 11);
        if(parameter & 0x0200) GPIOE->BSRRL |= (0X1 << 12); else GPIOE->BSRRH |= (0X1 << 12);
        if(parameter & 0x0400) GPIOE->BSRRL |= (0X1 << 13); else GPIOE->BSRRH |= (0X1 << 13);
        if(parameter & 0x0800) GPIOE->BSRRL |= (0X1 << 14); else GPIOE->BSRRH |= (0X1 << 14);
        if(parameter & 0x1000) GPIOE->BSRRL |= (0X1 << 15); else GPIOE->BSRRH |= (0X1 << 15);
        if(parameter & 0x2000) GPIOD->BSRRL |= (0X1 <<  8); else GPIOD->BSRRH |= (0X1 <<  8);
        if(parameter & 0x4000) GPIOD->BSRRL |= (0X1 <<  9); else GPIOD->BSRRH |= (0X1 <<  9);
        if(parameter & 0x8000) GPIOD->BSRRL |= (0X1 << 10); else GPIOD->BSRRH |= (0X1 << 10);
        WR = 1;
        CS = 1;
    }
    
    /*
    函数功能:清屏
    函数形参:清屏颜色
    函数返回值:无
    备注:无
    */
    void Lcd_Clear(u16 Color)
    {
        u32 index_value = 0;
        
        LCD_ILI9486_CMD(0X2A); 
        LCD_ILI9486_INDEX((0 & 0XFF00) >> 8);
        LCD_ILI9486_INDEX(0 & 0X00FF);
        LCD_ILI9486_INDEX((319 & 0XFF00) >> 8);
        LCD_ILI9486_INDEX(319 & 0X00FF);
        
        LCD_ILI9486_CMD(0X2B); 
        LCD_ILI9486_INDEX((0 & 0XFF00) >> 8);
        LCD_ILI9486_INDEX(0 & 0X00FF);
        LCD_ILI9486_INDEX((479 & 0XFF00) >> 8);
        LCD_ILI9486_INDEX(479 & 0X00FF);
        
        LCD_ILI9486_CMD(0X2C); 
        for(index_value = 0; index_value < 320 * 480; index_value++)
        {
            LCD_ILI9486_INDEX(Color);
        }
    }
    lcd_port_init(void)、、void LCD_ILI9486_CMD(u16 cmd)、、void Lcd_Clear(u16 Color)

    void at24c02_init(void)
    {
      iic_prot_init();
    }

    //STM32模拟IIC总线通信速度400KHz
    
    /*
    函数功能:初始化模拟IIC总线接口
    备注:PB8-SCL:推挽输出;PB9-SDA:开漏输出功能(推挽输出)
    */
    void iic_prot_init(void)
    {
        //开时钟
        RCC->AHB1ENR |= (0X1 << 1);
        //模式----普通输出
        GPIOB->MODER &= ~(0XF << 16);
        GPIOB->MODER |=  (0X5 << 16);
        //输出类型----推挽、开漏
        GPIOB->OTYPER &= ~(0X1 << 8);
        GPIOB->OTYPER |=  (0X1 << 9);
        //输出速度----低速
        GPIOB->OSPEEDR &= ~(0XF << 16);
        //上下拉----无上下拉
        GPIOB->PUPDR &= ~(0XF << 16);
        //SCL与SDA默认为高电平
        GPIOB->ODR |= (0X3 << 8);
    }
    
    /*
    函数功能:模拟IIC总线起始条件
    备注:SCL:推挽输出;SDA:开漏输出功能
    */
    void iic_start(void)
    {
        SCL = 1;
        SDA_OUT = 1;
        systick_delay_n_us(2);
        
        SDA_OUT = 0;
        systick_delay_n_us(2);
        
        SCL = 0;
    }
    
    /*
    函数功能:模拟IIC总线停止条件
    备注:SCL:推挽输出;SDA:开漏输出功能
    
    */
    void iic_stop(void)
    {
        SCL = 1;
        SDA_OUT = 0;
        systick_delay_n_us(2);
        
        SDA_OUT = 1;
        systick_delay_n_us(2);
    }
    
    /*
    函数功能:模拟IIC总线写一个字节
    函数形参:写的内容
    备注:SCL:推挽输出;SDA:开漏输出功能
    
    */
    void iic_write_byte(u8 byte_data)
    {
        u8 value = 0;
        
        for(value = 0; value < 8; value++)
        {
            SCL = 0;
            if(byte_data & (0x80 >> value))
            {
                SDA_OUT = 1;
            }
            else
            {
                SDA_OUT = 0;
            }
            systick_delay_n_us(2);
            
            SCL = 1;
            systick_delay_n_us(2);
        }
        
        SCL = 0;
    }
    
    /*
    函数功能:模拟IIC总线读一个字节
    函数返回值:读到的数据
    备注:SCL:推挽输出;SDA:开漏输出功能
    
    */
    u8 iic_read_byte(void)
    {
        u8 value = 0;
        u8 byte_data = 0;
        
        SDA_OUT = 1;//主设备释放SDA总线控制权
        /*配置SDA线为输入模式*/
        
        for(value = 0; value < 8; value++)
        {
            SCL = 0;
            systick_delay_n_us(2);
            
            SCL = 1;
            byte_data <<= 1;
            byte_data |= SDA_IN;
            systick_delay_n_us(2);
        }
        
        SCL = 0;
        /*配置SDA线为输出模式*/
        
        return byte_data;
    }
    
    /*
    函数功能:模拟IIC总线写应答位
    函数形参:写应答位
    备注:SCL:推挽输出;SDA:开漏输出功能
    
    */
    void iic_write_ack(u8 ack)
    {
        SCL = 0;
        if(ack)
        {
            SDA_OUT = 1;//非应答
        }
        else
        {
            SDA_OUT = 0;//应答
        }
        systick_delay_n_us(2);
        
        SCL = 1;
        systick_delay_n_us(2);
        
        SCL = 0;
    }
    
    /*
    函数功能:模拟IIC总线读应答位
    */
    u8 iic_read_ack(void)
    {
        u8 ack = 0;
        
        SDA_OUT = 1;//主设备释放SDA总线控制权
        /*配置SDA线为输入模式*/
        
        SCL = 0;
        systick_delay_n_us(2);
        
        SCL = 1;
        ack <<= 1;
        ack |= SDA_IN;
        systick_delay_n_us(2);
        
        SCL = 0;
        /*配置SDA线为输出模式*/
        
        return ack;
    }
    STM32模拟IIC总线通信速度400KHz
    void touch_init(void)
    {
        touch_prot_init();
        timer_7_init();
    
        //如果已经校正,则不需要调用此函数
        at24c02_sequential_read(0,sizeof(T_ADJUST_TYPE),(u8 *)&t_adjust_para);
    
        if(t_adjust_para.flag != T_ADJUST_OK)//没有校正,需要校正
        {
            touch_adjust();
        }
    }
    void touch_init(void)
    /*
    函数功能:触摸屏IO口初始化
    函数形参:无
    函数返回值:无
    备注:PB0-SCK、PC13-CS、PF11-MOSI、PB1-PEN、PB2-MISO
    */
    void touch_prot_init(void)
    {
        RCC->AHB1ENR |= 1 << 1;
        RCC->AHB1ENR |= 1 << 2;
        RCC->AHB1ENR |= 1 << 5;
        
        GPIOB->MODER &= ~(0X3F << 0);//PB1、PB2输入
        GPIOB->MODER |=  (0X1  << 0);//PB0输出
        
        GPIOB->OTYPER &= ~(0X1 << 0);//推挽
        GPIOB->OSPEEDR &= ~(0X3 << 0);//2M
        
        GPIOC->MODER &= ~(0X3 << 26);
        GPIOC->MODER |=  (0X1 << 26);//PC13输出
        
        GPIOC->ODR |= 1 << 13;//初始状态CS为高电平
        
        GPIOC->OTYPER &= ~(0X1 << 13);//推挽
        GPIOC->OSPEEDR &= ~(0X3 << 26);//2M
        
        GPIOF->MODER &= ~(0X3 << 22);
        GPIOF->MODER |=  (0X1 << 22);//PF11输出
        
        GPIOF->OTYPER &= ~(0X1 << 11);//推挽
        GPIOF->OSPEEDR &= ~(0X3 << 22);//2M
    }
    /*
    函数功能:读取AT24C02中的内容
    函数形参:写入的地址;写入的数量;写入的内容
    函数返回值:无
    备注:地址范围:0~255;write_number不能超过8
    */
    void at24c02_sequential_read(u8 subaddr,u8 read_number,u8 * read_data)
    {
        u8 value = 0;
        
        iic_start();
        
        iic_write_byte(ADDR_WRITE);
        if(iic_read_ack())
        {
            printf("file: %s	line: %d
    ",__FILE__, __LINE__);
            return ;
        }
        
        iic_write_byte(subaddr);
        if(iic_read_ack())
        {
            printf("file: %s	line: %d
    ",__FILE__, __LINE__);
            return ;
        }
        
        iic_start();
        
        iic_write_byte(ADDR_READ);
        if(iic_read_ack())
        {
            printf("file: %s	line: %d
    ",__FILE__, __LINE__);
            return ;
        }
        
        for(value = 0; value < read_number - 1; value++)
        {
            *read_data = iic_read_byte();
            read_data++;
            
            iic_write_ack(0);
        }
        *read_data = iic_read_byte();
        iic_write_ack(1);
        
        iic_stop();
    }
    touch_prot_init(void)、、读取AT24C02中的内容

    while(1)
    {

    if(t_para.sta.hold == 1)//按下
    {
    if(HUMITURE)
    {
    humiture();//步进电机
    }

    if(SMOG)
    {
    smoke_transducer();//烟雾传感器
    }

    if(RGB_LED)
    {
    rgb_led();//彩灯
    }

    if(INFRARED)
    {
    infrared();
    }

    }

    111

  • 相关阅读:
    Django-建立网页
    selenium、unittest——POM框架并出报告
    unittest,requests——接口测试脚本及报告
    从浏览器地址栏输入网址,到网页彻底打开,中间都发生了什么?
    HTTP结构讲解——《HTTP权威指南》系列
    charles基本使用文档
    接口测试操作指引
    环境更新
    Linux查看文件内容
    通过Jmeter对Dubbo接口进行接口及性能测试
  • 原文地址:https://www.cnblogs.com/zhouyuqing1024/p/11865129.html
Copyright © 2020-2023  润新知