基于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\tline: %d\r\n",__FILE__, __LINE__);
        return ;
    }
    
    iic_write_byte(subaddr);
    if(iic_read_ack())
    {
        printf("file: %s\tline: %d\r\n",__FILE__, __LINE__);
        return ;
    }
    
    iic_start();
    
    iic_write_byte(ADDR_READ);
    if(iic_read_ack())
    {
        printf("file: %s\tline: %d\r\n",__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

猜你喜欢

转载自www.cnblogs.com/zhouyuqing1024/p/11865129.html