//USB中断配置 void USB_Interrupts_Config(void) { EXTI->IMR|=1<<18;// 开启线18上的中断 EXTI->RTSR|=1<<18;//line 18上事件上升降沿触发 MY_NVIC_Init(1,1,USB_LP_CAN_RX0_IRQChannel,2);//组2,优先级次之 MY_NVIC_Init(0,1,USBWakeUp_IRQChannel,2); //组2,优先级最高 }
//初始化IO 串口1 //pclk2:PCLK2时钟频率(Mhz) //bound:波特率 void uart_init(u32 pclk2,u32 bound) { float temp; u16 mantissa; u16 fraction; temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV@OVER8=0 mantissa=temp; //得到整数部分 fraction=(temp-mantissa)*16; //得到小数部分@OVER8=0 mantissa<<=4; mantissa+=fraction; RCC->AHB1ENR|=1<<0; //使能PORTA口时钟 RCC->APB2ENR|=1<<4; //使能串口1时钟 GPIO_Set(GPIOA,PIN9|PIN10,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PU);//PA9,PA10,复用功能,上拉输出 GPIO_AF_Set(GPIOA,9,7); //PA9,AF7 GPIO_AF_Set(GPIOA,10,7);//PA10,AF7 //波特率设置 USART1->BRR=mantissa; //波特率设置 USART1->CR1&=~(1<<15); //设置OVER8=0 USART1->CR1|=1<<3; //串口发送使能 #if EN_USART1_RX //如果使能了接收 //使能接收中断 USART1->CR1|=1<<2; //串口接收使能 USART1->CR1|=1<<5; //接收缓冲区非空中断使能 MY_NVIC_Init(3,3,USART1_IRQn,2);//组2,最低优先级 #endif USART1->CR1|=1<<13; //串口使能 }
//设置闹钟时间(按星期闹铃,24小时制) //week:星期几(1~7) //hour,min,sec:小时,分钟,秒钟 void RTC_Set_AlarmA(u8 week,u8 hour,u8 min,u8 sec) { //关闭RTC寄存器写保护 RTC->WPR=0xCA; RTC->WPR=0x53; RTC->CR&=~(1<<8); //关闭闹钟A while((RTC->ISR&0X01)==0);//等待闹钟A修改允许 RTC->ALRMAR=0; //清空原来设置 RTC->ALRMAR|=1<<30; //按星期闹铃 RTC->ALRMAR|=0<<22; //24小时制 RTC->ALRMAR|=(u32)RTC_DEC2BCD(week)<<24;//星期设置 RTC->ALRMAR|=(u32)RTC_DEC2BCD(hour)<<16;//小时设置 RTC->ALRMAR|=(u32)RTC_DEC2BCD(min)<<8; //分钟设置 RTC->ALRMAR|=(u32)RTC_DEC2BCD(sec); //秒钟设置 RTC->ALRMASSR=0; //不使用SUB SEC RTC->CR|=1<<12; //开启闹钟A中断 RTC->CR|=1<<8; //开启闹钟A RTC->WPR=0XFF; //禁止修改RTC寄存器 RTC->ISR&=~(1<<8); //清除RTC闹钟A的标志 EXTI->PR=1<<17; //清除LINE17上的中断标志位 EXTI->IMR|=1<<17; //开启line17上的中断 EXTI->RTSR|=1<<17; //line17上事件上升降沿触发 MY_NVIC_Init(2,2,RTC_Alarm_IRQn,2); //抢占2,子优先级2,组2 }
//初始化IO 串口1 //pclk2:PCLK2时钟频率(Mhz) //bound:波特率 //CHECK OK //091209 void uart_init(u32 pclk2,u32 bound) { float temp; u16 mantissa; u16 fraction; temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV mantissa=temp; //得到整数部分 fraction=(temp-mantissa)*16; //得到小数部分 mantissa<<=4; mantissa+=fraction; RCC->APB2ENR|=1<<2; //使能PORTA口时钟 RCC->APB2ENR|=1<<14; //使能串口时钟 GPIOA->CRH&=0XFFFFF00F;//IO状态设置 GPIOA->CRH|=0X000008B0;//IO状态设置 RCC->APB2RSTR|=1<<14; //复位串口1 RCC->APB2RSTR&=~(1<<14);//停止复位 //波特率设置 USART1->BRR=mantissa; // 波特率设置 USART1->CR1|=0X200C; //1位停止,无校验位. //使能接收中断 USART1->CR1|=1<<8; //PE中断使能 USART1->CR1|=1<<5; //接收缓冲区非空中断使能 //USART1->CR1|=1<<7; USART1->CR1|=1<<7; //TXE发送缓冲区空中断使能 MY_NVIC_Init(3,3,USART1_IRQChannel,2);//组2,最低优先级 }
/******************************************************************************* 函 数 名: USART_Init 功能说明: 串口初始化 参 数: pclk2: 时钟频率(单位M) bound: 通信波特率 返 回 值: 无 *******************************************************************************/ void USART_Init(BF_INT32U bound) { RCC_ClocksTypeDef RCC_ClocksStatus; RCC_GetClocksFreq(&RCC_ClocksStatus);//配置串口波特率 RCC->APB2RSTR |= 1<<14; //复位串口1 RCC->APB2RSTR &= ~(1<<14); //停止复位 RCC->AHBENR |= 1<<0; //使能PORTA口时钟 RCC->APB2ENR |= 1<<14; //使能串口时钟 GPIOA->MODER &= 0xFFC3FFFF; //PA9,PA10管脚复用 GPIOA->MODER |= 0x00280000; GPIOA->OTYPER&= 0xFFFFF9FF; //设置管脚推挽输出 GPIOA->OSPEEDR&= 0xFFC3FFFF; //设置管脚速度40M GPIOA->OSPEEDR|= 0x003C0000; GPIOA->PUPDR &= 0xFFC3FFFF; //管脚不上下拉 GPIOA->AFR[1] &= 0xFFFFFFFF; //设置复用功能 GPIOA->AFR[1] |= 0x00000770; //波特率设置 USART1->BRR = (RCC_ClocksStatus.PCLK2_Frequency)/(bound); // 波特率设置 USART1->CR1 |= 0X200C; //1位停止,无校验位. USART1->CR1 |= 1<<8; //PE中断使能 USART1->CR1 |= 1<<5; //接收缓冲区非空中断使能 MY_NVIC_Init(3, 3, USART1_IRQn, 2);//组2,最低优先级 }
//DCMI DMA配置 //mem0addr:存储器地址0 将要存储摄像头数据的内存地址(也可以是外设地址) //mem1addr:存储器地址1 当只使用mem0addr的时候,该值必须为0 //memsize:存储器长度 0~65535 //memblen:存储器位宽 0,8位,1,16位,2,32位 //meminc:存储器增长方式,0,不增长;1,增长 void DCMI_DMA_Init(u32 mem0addr,u32 mem1addr,u16 memsize,u8 memblen,u8 meminc) { RCC->AHB1ENR|=1<<22; //DMA2时钟使能 while(DMA2_Stream1->CR&0X01);//等待DMA2_Stream1可配置 DMA2->LIFCR|=0X3D<<6*1; //清空通道1上所有中断标志 DMA2_Stream1->FCR=0X0000021;//设置为默认值 DMA2_Stream1->PAR=(u32)&DCMI->DR;//外设地址为:DCMI->DR DMA2_Stream1->M0AR=mem0addr; //mem0addr作为目标地址0 DMA2_Stream1->M1AR=mem1addr; //mem1addr作为目标地址1 DMA2_Stream1->NDTR=memsize; //传输长度为memsize DMA2_Stream1->CR=0; //先全部复位CR寄存器值 DMA2_Stream1->CR|=0<<6; //外设到存储器模式 DMA2_Stream1->CR|=1<<8; //循环模式 DMA2_Stream1->CR|=0<<9; //外设非增量模式 DMA2_Stream1->CR|=meminc<<10; //存储器增量模式 DMA2_Stream1->CR|=2<<11; //外设数据长度:32位 DMA2_Stream1->CR|=memblen<<13; //存储器位宽,8/16/32bit DMA2_Stream1->CR|=2<<16; //高优先级 DMA2_Stream1->CR|=0<<21; //外设突发单次传输 DMA2_Stream1->CR|=0<<23; //存储器突发单次传输 DMA2_Stream1->CR|=1<<25; //通道1 DCMI通道 if(mem1addr)//双缓冲的时候,才需要开启 { DMA2_Stream1->CR|=1<<18; //双缓冲模式 DMA2_Stream1->CR|=1<<4; //开启传输完成中断 MY_NVIC_Init(0,0,DMA2_Stream1_IRQn,2); //抢占1,子优先级3,组2 } }
void uart3_init(u32 pclk2,u32 bound) { float temp; u16 mantissa; u16 fraction; temp=(float)(pclk2*1000000/2)/(bound*16);//得到USARTDIV mantissa=temp; //得到整数部分 fraction=(temp-mantissa)*16; //得到小数部分 mantissa<<=4; mantissa+=fraction; //AFIO->MAPR &= ~AFIO_MAPR_USART1_REMAP; RCC->APB2ENR|=1<<3; //使能PORTA口时钟 RCC->APB1ENR|=1<<18; //使能串口时钟 GPIOB->CRH&=0XFFFF00FF; GPIOB->CRH|=0X00008B00;//IO状态设置 GPIOB->ODR|=1<<10; RCC->APB1RSTR|=1<<18; //复位串口1 RCC->APB1RSTR&=~(1<<18);//停止复位 //波特率设置 USART3->BRR=mantissa; // 波特率设置 USART3->CR1|=0X200C; //1位停止,无校验位. //使能接收中断 USART3->CR1|=1<<8; //PE中断使能 USART3->CR1|=1<<5; //接收缓冲区非空中断使能 MY_NVIC_Init(1,3,USART3_IRQChannel,2);//组2,最低优先级 }
/******************************************************************************* **函 数: USART1_Init() **功 能: 串口1初始化 **参 数: pclk1 --PCLK1时钟频率(Mhz) 默认使用32M bound --波特率 **返 回: null **说 明: ********************************************************************************/ void USART2_Init(u32 pclk1,u32 bound) { float temp; u16 mantissa; u16 fraction; temp=(float)(pclk1*1000000)/(bound*16);//得到USARTDIV mantissa=temp; //得到整数部分 fraction=(temp-mantissa)*16; //得到小数部分 mantissa<<=4; mantissa+=fraction; RCC->AHBENR |=1<<0; //使能PORTA口时钟 RCC->APB1ENR|=1<<17; //使能串口2时钟 RCC->APB1RSTR|= 1<<17; //复位串口1 RCC->APB1RSTR&=~(1<<17); //停止复位 GPIOx_Cfg(GPIO_A,pin_2,AF_PP_40M); //TX GPIOx_AF( GPIO_A,pin_2,AF_USART1); GPIOx_Cfg(GPIO_A,pin_3,AF_PP_40M); //RX 变态设置 GPIOx_AF( GPIO_A,pin_3,AF_USART1); USART2->BRR = mantissa; // 波特率设置 USART2->CR1|=(1<<13)|(1<<3)|(1<<2); //(UE)使能usart1 (TE)使能发送 (RE)使能接收//8bit数据 1bit停止,无校验位. //while((USART1->SR&(1<<6))==0) {} //等待发送完成 #if EN_USART2_RX //如果使能了接收 USART2->CR2|=(1<<5); //(RXNEIE)接收中断使能 MY_NVIC_Init(2,2,USART2_IRQn,2); #endif }
//CAN初始化 //tsjw:重新同步跳跃时间单元.范围:1~3; //tbs2:时间段2的时间单元.范围:1~8; //tbs1:时间段1的时间单元.范围:1~16; //brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1 //注意以上参数任何一个都不能设为0,否则会乱. //波特率=Fpclk1/((tbs1+tbs2+1)*brp); //mode:0,普通模式;1,回环模式; //Fpclk1的时钟在初始化的时候设置为42M,如果设置CAN1_Mode_Init(1,6,7,6,1); //则波特率为:42M/((6+7+1)*6)=500Kbps //返回值:0,初始化OK; // 其他,初始化失败; u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode) { u16 i=0; if(tsjw==0||tbs2==0||tbs1==0||brp==0)return 1; tsjw-=1;//先减去1.再用于设置 tbs2-=1; tbs1-=1; brp-=1; RCC->AHB1ENR|=1<<0; //使能PORTA口时钟 GPIO_Set(GPIOA,PIN11|PIN12,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PU);//PA11,PA12,复用功能,上拉输出 GPIO_AF_Set(GPIOA,11,9);//PA11,AF9 GPIO_AF_Set(GPIOA,12,9);//PA12,AF9 RCC->APB1ENR|=1<<25;//使能CAN1时钟 CAN1使用的是APB1的时钟(max:42M) CAN1->MCR=0x0000; //退出睡眠模式(同时设置所有位为0) CAN1->MCR|=1<<0; //请求CAN进入初始化模式 while((CAN1->MSR&1<<0)==0) { i++; if(i>100)return 2;//进入初始化模式失败 } CAN1->MCR|=0<<7; //非时间触发通信模式 CAN1->MCR|=0<<6; //软件自动离线管理 CAN1->MCR|=0<<5; //睡眠模式通过软件唤醒(清除CAN1->MCR的SLEEP位) CAN1->MCR|=1<<4; //禁止报文自动传送 CAN1->MCR|=0<<3; //报文不锁定,新的覆盖旧的 CAN1->MCR|=0<<2; //优先级由报文标识符决定 CAN1->BTR=0x00000000; //清除原来的设置. CAN1->BTR|=mode<<30; //模式设置 0,普通模式;1,回环模式; CAN1->BTR|=tsjw<<24; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN1->BTR|=tbs2<<20; //Tbs2=tbs2+1个时间单位 CAN1->BTR|=tbs1<<16; //Tbs1=tbs1+1个时间单位 CAN1->BTR|=brp<<0; //分频系数(Fdiv)为brp+1 //波特率:Fpclk1/((Tbs1+Tbs2+1)*Fdiv) CAN1->MCR&=~(1<<0); //请求CAN退出初始化模式 while((CAN1->MSR&1<<0)==1) { i++; if(i>0XFFF0)return 3;//退出初始化模式失败 } //过滤器初始化 CAN1->FMR|=1<<0; //过滤器组工作在初始化模式 CAN1->FA1R&=~(1<<0); //过滤器0不激活 CAN1->FS1R|=1<<0; //过滤器位宽为32位. CAN1->FM1R|=0<<0; //过滤器0工作在标识符屏蔽位模式 CAN1->FFA1R|=0<<0; //过滤器0关联到FIFO0 CAN1->sFilterRegister[0].FR1=0X00000000;//32位ID CAN1->sFilterRegister[0].FR2=0X00000000;//32位MASK CAN1->FA1R|=1<<0; //激活过滤器0 CAN1->FMR&=0<<0; //过滤器组进入正常模式 #if CAN1_RX0_INT_ENABLE //使用中断接收 CAN1->IER|=1<<1; //FIFO0消息挂号中断允许. MY_NVIC_Init(1,0,CAN1_RX0_IRQn,2);//组2 #endif return 0; }
//CAN初始化 //tsjw:重新同步跳跃时间单元.范围:1~3; //tbs2:时间段2的时间单元.范围:1~8; //tbs1:时间段1的时间单元.范围:1~16; //brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1 //注意以上参数任何一个都不能设为0,否则会乱. //波特率=Fpclk1/((tbs1+tbs2+1)*brp); //mode:0,普通模式;1,回环模式; //Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Normal_Init(1,8,7,5,1); //则波特率为:36M/((8+7+1)*5)=450Kbps //返回值:0,初始化OK; // 其他,初始化失败; u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode) { u16 i=0; if(tsjw==0||tbs2==0||tbs1==0||brp==0)return 1; tsjw-=1;//先减去1.再用于设置 tbs2-=1; tbs1-=1; brp-=1; RCC->APB2ENR|=1<<2; //使能PORTA时钟 GPIOA->CRH&=0XFFF00FFF; GPIOA->CRH|=0X000B8000;//PA11 RX,PA12 TX推挽输出 GPIOA->ODR|=3<<11; RCC->APB1ENR|=1<<25;//使能CAN时钟 CAN使用的是APB1的时钟(max:36M) CAN->MCR=0x0000; //退出睡眠模式(同时设置所有位为0) CAN->MCR|=1<<0; //请求CAN进入初始化模式 while((CAN->MSR&1<<0)==0) { i++; if(i>100)return 2;//进入初始化模式失败 } CAN->MCR|=0<<7; //非时间触发通信模式 CAN->MCR|=0<<6; //软件自动离线管理 CAN->MCR|=0<<5; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位) CAN->MCR|=1<<4; //禁止报文自动传送 CAN->MCR|=0<<3; //报文不锁定,新的覆盖旧的 CAN->MCR|=0<<2; //优先级由报文标识符决定 CAN->BTR=0x00000000;//清除原来的设置. CAN->BTR|=mode<<30; //模式设置 0,普通模式;1,回环模式; CAN->BTR|=tsjw<<24; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN->BTR|=tbs2<<20; //Tbs2=tbs2+1个时间单位 CAN->BTR|=tbs1<<16; //Tbs1=tbs1+1个时间单位 CAN->BTR|=brp<<0; //分频系数(Fdiv)为brp+1 //波特率:Fpclk1/((Tbs1+Tbs2+1)*Fdiv) CAN->MCR&=~(1<<0); //请求CAN退出初始化模式 while((CAN->MSR&1<<0)==1) { i++; if(i>0XFFF0)return 3;//退出初始化模式失败 } //过滤器初始化 CAN->FMR|=1<<0; //过滤器组工作在初始化模式 CAN->FA1R&=~(1<<0); //过滤器0不激活 CAN->FS1R|=1<<0; //过滤器位宽为32位. CAN->FM1R|=0<<0; //过滤器0工作在标识符屏蔽位模式 CAN->FFA1R|=0<<0; //过滤器0关联到FIFO0 CAN->sFilterRegister[0].FR1=0X00000000;//32位ID CAN->sFilterRegister[0].FR2=0X00000000;//32位MASK CAN->FA1R|=1<<0; //激活过滤器0 CAN->FMR&=0<<0; //过滤器组进入正常模式 #if CAN_RX0_INT_ENABLE //使用中断接收 CAN->IER|=1<<1; //FIFO0消息挂号中断允许. MY_NVIC_Init(1,0,USB_LP_CAN_RX0_IRQChannel,2);//组2 #endif return 0; }
void EXTIX_Init(void) { KEY_Init(); //配置键盘中断触发方式 Ex_NVIC_Config(GPIO_E,2,FTIR); Ex_NVIC_Config(GPIO_E,3,FTIR); Ex_NVIC_Config(GPIO_E,4,FTIR);//上拉,默认高电平,下降沿触发 Ex_NVIC_Config(GPIO_A,0,RTIR);//下拉,默认低电平,上升沿触发 //设置中断分组 MY_NVIC_Init(3,2,EXTI2_IRQn,2);//抢占优先级为3,子优先级为2,中断分组为第2组[2位抢占优先级(有4个抢占优先级),2位响应优先级(有4个)] MY_NVIC_Init(2,2,EXTI3_IRQn,2); MY_NVIC_Init(1,2,EXTI4_IRQn,2); MY_NVIC_Init(0,2,EXTI0_IRQn,2); }
//使能定时器4,使能中断. void Timer4_Init(u16 arr,u16 psc) { RCC->APB1ENR|=1<<2; //TIM4 时钟使能 TIM4->ARR=arr; //设定计数器自动重装值 TIM4->PSC=psc; //预分频器7200,得到10Khz的计数时钟 TIM4->DIER|=1<<0; //允许更新中断 TIM4->CR1|=0x01; //使能定时器4 MY_NVIC_Init(3,3,TIM4_IRQn,2);//抢占3,子优先级3,组2(组2中优先级最低的) }
void EXTIX_Init(void) { JTAG_Set(JTAG_SWD_DISABLE);//turn off JTAG&SWD Ex_NVIC_Config(GPIO_B,0,0x03); //edge trigger MY_NVIC_Init(1,1,EXTI0_IRQChannel,2); }
//外部中断初始化程序 //初始化PA0,PA13,PA15为中断输入. void EXTIX_Init(void) { RCC->APB2ENR|=1<<2; //使能PORTA时钟 JTAG_Set(JTAG_SWD_DISABLE);//关闭JTAG和SWD GPIOA->CRL&=0XFFFFFFF0;//PA0设置成输入 GPIOA->CRL|=0X00000008; GPIOA->CRH&=0X0F0FFFFF;//PA13,15设置成输入 GPIOA->CRH|=0X80800000; GPIOA->ODR|=1<<13; //PA13上拉,PA0默认下拉 GPIOA->ODR|=1<<15; //PA15上拉 Ex_NVIC_Config(GPIOA,0,RTIR); //上升沿触发 Ex_NVIC_Config(GPIOA,13,FTIR);//下降沿触发 Ex_NVIC_Config(GPIOA,15,FTIR);//下降沿触发 MY_NVIC_Init(2,2,EXTI0_IRQn,2); //抢占2,子优先级2,组2 MY_NVIC_Init(2,1,EXTI15_10_IRQn,2);//抢占2,子优先级1,组2 }
/******************************************************************* 函 数 名: UART_Init 功能说明: 串口初始化 参 数: pclk2: 时钟频率(单位M) bound: 通信波特率 返 回 值: 无 *******************************************************************/ void UART_Init(u32 pclk2, u32 bound) { // u8 a[7] = {0}; // u8 len = 7; // u8 i = 0; #if (USART == 1) RCC->APB2RSTR |= UART_CLK; RCC->APB2RSTR &= ~(UART_CLK); RCC->APB2ENR |= UART_CLK; #elif (USART == 2) RCC->APB1RSTR |= UART_CLK; RCC->APB1RSTR &= ~(UART_CLK); RCC->APB1ENR |= UART_CLK; #elif (USART == 3) RCC->APB1RSTR |= UART_CLK; RCC->APB1RSTR &= ~(UART_CLK); RCC->APB1ENR |= UART_CLK; #endif GPIOx_Cfg(UART_PORT, UART_TX_PIN, AF_PP_50M); GPIOx_Cfg(UART_PORT, UART_RX_PIN, IN_UPDOWN); #if (USART == 1) UART->BRR = (pclk2*1000000)/(bound); #elif (USART == 2) UART->BRR = (pclk2*1000000/2)/(bound); #elif (USART == 3) UART->BRR = (pclk2*1000000/2)/(bound); #endif UART->CR1|=(1<<13)|(1<<3)|(1<<2)|(1<<8); UART->CR1|=(1<<5); #if (USART == 1) MY_NVIC_Init( 2, 1, USART1_IRQn, 2); #elif (USART == 2) MY_NVIC_Init( 2, 1, USART2_IRQn, 2); #elif (USART == 3) MY_NVIC_Init( 2, 2, USART3_IRQn, 2); #endif }
//初始化窗口看门狗 //tr :T[6:0],用于存储计数器的值 //wr :W[6:0],用于存储窗口值 //fprer:窗口看门狗的实际设置 //低2位有效.Fwwdg=PCLK1/4096/2^fprer. void WWDG_Init(u8 tr,u8 wr,u8 fprer) { RCC->APB1ENR|=1<<11; //使能wwdg时钟 WWDG_CNT=tr&WWDG_CNT; //初始化WWDG_CNT. WWDG->CFR|=fprer<<7; //PCLK1/4096再除2^fprer WWDG->CFR|=1<<9; //使能中断 WWDG->CFR&=0XFF80; WWDG->CFR|=wr; //设定窗口值 WWDG->CR|=WWDG_CNT|(1<<7); //开启看门狗,设置7位计数器 MY_NVIC_Init(2,3,WWDG_IRQChannel,2);//抢占2,子优先级3,组2 }
//使能定时器2,使能中断. void Timer2_Init(u16 arr,u16 psc) { RCC->APB1ENR|=1<<0;//TIM2时钟使能 TIM2->ARR=arr; //设定计数器自动重装值 TIM2->PSC=psc; //预分频器7200,得到10Khz的计数时钟 //这两个东东要同时设置才可以使用中断 TIM2->DIER|=1<<0; //允许更新中断 TIM2->DIER|=1<<6; //允许触发中断 TIM2->CR1|=0x01; //使能定时器2 MY_NVIC_Init(3,3,TIM2_IRQChannel,2);//抢占3,子优先级3,组2(组2中优先级最低的) }
//PA0 WKUP唤醒初始化 void WKUP_Init(void) { RCC->APB2ENR|=1<<2; //先使能外设IO PORTA时钟 RCC->APB2ENR|=1<<0; //开启辅助时钟 GPIOA->CRL&=0XFFFFFFF0;//PA0设置成输入 GPIOA->CRL|=0X00000008; Ex_NVIC_Config(GPIO_A,0,RTIR);//PA0上升沿触发 //(检查是否是正常开)机 if(Check_WKUP()==0)Sys_Standby(); //不是开机,进入待机模式 MY_NVIC_Init(2,2,EXTI0_IRQChannel,2);//抢占2,子优先级2,组2 }
//初始化窗口看门狗 //tr :T[6:0],计数器值 //wr :W[6:0],窗口值 //fprer:分频系数(WDGTB),仅最低2位有效 //Fwwdg=PCLK1/(4096*2^fprer). 一般PCLK1=42Mhz void WWDG_Init(u8 tr,u8 wr,u8 fprer) { RCC->APB1ENR|=1<<11; //使能wwdg时钟 WWDG_CNT=tr&WWDG_CNT; //初始化WWDG_CNT. WWDG->CFR|=fprer<<7; //PCLK1/4096再除2^fprer WWDG->CFR&=0XFF80; WWDG->CFR|=wr; //设定窗口值 WWDG->CR|=WWDG_CNT; //设定计数器值 WWDG->CR|=1<<7; //开启看门狗 MY_NVIC_Init(2,3,WWDG_IRQn,2);//抢占2,子优先级3,组2 WWDG->SR=0X00; //清除提前唤醒中断标志位 WWDG->CFR|=1<<9; //使能提前唤醒中断 }
//外部中断初始化程序 //初始化PA0,PA13,PA15为中断输入. void EXTIX_Init(void) { RCC->APB2ENR|=1<<2; //使能PORTA时钟 JTAG_Set(JTAG_SWD_DISABLE);//关闭JTAG和SWD // GPIOA->CRL&=0XFFFFFFF0;//PA0设置成输入 // GPIOA->CRL|=0X00000008; GPIOA->CRH&=0X0FFFFFFF;//PA15设置成输入 GPIOA->CRH|=0X80000000; GPIOA->ODR|=1<<15; //PA15上拉 // Ex_NVIC_Config(GPIO_A,0,RTIR); //上升沿触发 // Ex_NVIC_Config(GPIO_A,13,FTIR);//下降沿触发 Ex_NVIC_Config(GPIO_A,15,RTIR);//下降沿触发 // MY_NVIC_Init(2,2,EXTI0_IRQChannel,2); //抢占2,子优先级2,组2 MY_NVIC_Init(2,1,EXTI15_10_IRQChannel,2);//抢占2,子优先级1,组2 }
//初始化SD卡 //返回值:错误代码;(0,无错误) SD_Error SD_Init(void) { SD_Error errorstatus=SD_OK; u8 clkdiv=0; //SDIO IO口初始化 RCC->AHB1ENR|=1<<2; //使能PORTC时钟 RCC->AHB1ENR|=1<<3; //使能PORTD时钟 RCC->AHB1ENR|=1<<22; //DMA2时钟使能 RCC->APB2ENR|=1<<11; //SDIO时钟使能 RCC->APB2RSTR|=1<<11; //SDIO复位 GPIO_Set(GPIOC,0X1F<<8,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PU); //PC8,9,10,11,12复用功能输出 GPIO_Set(GPIOD,1<<2,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PU); //PD2复用功能输出 GPIO_AF_Set(GPIOC,8,12); //PC8,AF12 GPIO_AF_Set(GPIOC,9,12); //PC9,AF12 GPIO_AF_Set(GPIOC,10,12); //PC10,AF12 GPIO_AF_Set(GPIOC,11,12); //PC11,AF12 GPIO_AF_Set(GPIOC,12,12); //PC12,AF12 GPIO_AF_Set(GPIOD,2,12); //PD2,AF12 RCC->APB2RSTR&=~(1<<11); //SDIO结束复位 //SDIO外设寄存器设置为默认值 SDIO->POWER=0x00000000; SDIO->CLKCR=0x00000000; SDIO->ARG=0x00000000; SDIO->CMD=0x00000000; SDIO->DTIMER=0x00000000; SDIO->DLEN=0x00000000; SDIO->DCTRL=0x00000000; SDIO->ICR=0x00C007FF; SDIO->MASK=0x00000000; MY_NVIC_Init(0,0,SDIO_IRQn,2); //SDIO中断配置 errorstatus=SD_PowerON(); //SD卡上电 if(errorstatus==SD_OK)errorstatus=SD_InitializeCards(); //初始化SD卡 if(errorstatus==SD_OK)errorstatus=SD_GetCardInfo(&SDCardInfo); //获取卡信息 if(errorstatus==SD_OK)errorstatus=SD_SelectDeselect((u32)(SDCardInfo.RCA<<16));//选中SD卡 if(errorstatus==SD_OK)errorstatus=SD_EnableWideBusOperation(1); //4位宽度,如果是MMC卡,则不能用4位模式 if((errorstatus==SD_OK)||(SDIO_MULTIMEDIA_CARD==CardType)) { if(SDCardInfo.CardType==SDIO_STD_CAPACITY_SD_CARD_V1_1||SDCardInfo.CardType==SDIO_STD_CAPACITY_SD_CARD_V2_0) { clkdiv=SDIO_TRANSFER_CLK_DIV+2; //V1.1/V2.0卡,设置最高48/4=12Mhz }else clkdiv=SDIO_TRANSFER_CLK_DIV; //SDHC等其他卡,设置最高48/2=24Mhz SDIO_Clock_Set(clkdiv); //设置时钟频率,SDIO时钟计算公式:SDIO_CK时钟=SDIOCLK/[clkdiv+2];其中,SDIOCLK固定为48Mhz //errorstatus=SD_SetDeviceMode(SD_DMA_MODE); //设置为DMA模式 errorstatus=SD_SetDeviceMode(SD_POLLING_MODE);//设置为查询模式 } return errorstatus; }
//实时时钟配置 //初始化RTC时钟,同时检测时钟是否工作正常 //BKP->DR1用于保存是否第一次配置的设置 //返回0:正常 //其他:错误代码 u8 RTC_Init(void) { //检查是不是第一次配置时钟 u8 temp=0; if(BKP->DR1!=0X5050)//第一次配置 { RCC->APB1ENR|=1<<28; //使能电源时钟 RCC->APB1ENR|=1<<27; //使能备份时钟 PWR->CR|=1<<8; //取消备份区写保护 RCC->BDCR|=1<<16; //备份区域软复位 RCC->BDCR&=~(1<<16); //备份区域软复位结束 RCC->BDCR|=1<<0; //开启外部低速振荡器 while((!(RCC->BDCR&0X02))&&temp<250)//等待外部时钟就绪 { temp++; delay_ms(10); }; if(temp>=250)return 1;//初始化时钟失败,晶振有问题 RCC->BDCR|=1<<8; //LSI作为RTC时钟 RCC->BDCR|=1<<15;//RTC时钟使能 while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成 while(!(RTC->CRL&(1<<3)));//等待RTC寄存器同步 RTC->CRH|=0X01; //允许秒中断 while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成 RTC->CRL|=1<<4; //允许配置 RTC->PRLH=0X0000; RTC->PRLL=32767; //时钟周期设置(有待观察,看是否跑慢了?)理论值:32767 Auto_Time_Set(); //RTC_Set(2009,12,2,10,0,55); //设置时间 RTC->CRL&=~(1<<4); //配置更新 while(!(RTC->CRL&(1<<5))); //等待RTC寄存器操作完成 BKP->DR1=0X5050; //BKP_Write(1,0X5050);;//在寄存器1标记已经开启了 //printf("FIRST TIME\n"); }else//系统继续计时 { while(!(RTC->CRL&(1<<3)));//等待RTC寄存器同步 RTC->CRH|=0X01; //允许秒中断 while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成 //printf("OK\n"); } MY_NVIC_Init(0,0,RTC_IRQChannel,2);//RTC,G2,P2,S2.优先级最低 RTC_Get();//更新时间 return 0; //ok }
//DCMI初始化 void DCMI_Init(void) { //设置IO RCC->AHB1ENR|=1<<0; //使能外设PORTA时钟 RCC->AHB1ENR|=1<<1; //使能外设PORTB时钟 RCC->AHB1ENR|=1<<2; //使能外设PORTC时钟 RCC->AHB1ENR|=1<<4; //使能外设PORTE时钟 RCC->AHB2ENR|=1<<0; //能DCMI时钟 GPIO_Set(GPIOA,PIN4|PIN6,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PA4/6 复用功能输出 GPIO_Set(GPIOB,PIN6|PIN7,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PB6/7 复用功能输出 GPIO_Set(GPIOC,PIN6|PIN7|PIN8|PIN9|PIN11,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);//PC6/7/8/9/11 复用功能输出 GPIO_Set(GPIOE,PIN5|PIN6,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PE5/6 复用功能输出 GPIO_AF_Set(GPIOA,4,13); //PA4,AF13 DCMI_HSYNC GPIO_AF_Set(GPIOA,6,13); //PA6,AF13 DCMI_PCLK GPIO_AF_Set(GPIOB,7,13); //PB7,AF13 DCMI_VSYNC GPIO_AF_Set(GPIOC,6,13); //PC6,AF13 DCMI_D0 GPIO_AF_Set(GPIOC,7,13); //PC7,AF13 DCMI_D1 GPIO_AF_Set(GPIOC,8,13); //PC8,AF13 DCMI_D2 GPIO_AF_Set(GPIOC,9,13); //PC9,AF13 DCMI_D3 GPIO_AF_Set(GPIOC,11,13); //PC11,AF13 DCMI_D4 GPIO_AF_Set(GPIOB,6,13); //PB6,AF13 DCMI_D5 GPIO_AF_Set(GPIOE,5,13); //PE5,AF13 DCMI_D6 GPIO_AF_Set(GPIOE,6,13); //PE6,AF13 DCMI_D7 //清除原来的设置 DCMI->CR=0x0; DCMI->IER=0x0; DCMI->ICR=0x1F; DCMI->ESCR=0x0; DCMI->ESUR=0x0; DCMI->CWSTRTR=0x0; DCMI->CWSIZER=0x0; DCMI->CR|=0<<1; //连续模式 DCMI->CR|=0<<2; //全帧捕获 DCMI->CR|=0<<4; //硬件同步HSYNC,VSYNC DCMI->CR|=1<<5; //PCLK 上升沿有效 DCMI->CR|=0<<6; //HSYNC 低电平有效 DCMI->CR|=0<<7; //VSYNC 低电平有效 DCMI->CR|=0<<8; //捕获所有的帧 DCMI->CR|=0<<10; //8位数据格式 DCMI->IER|=1<<0; //开启帧中断 DCMI->CR|=1<<14; //DCMI使能 MY_NVIC_Init(0,0,DCMI_IRQn,2); //抢占1,子优先级2,组2 }
//周期性唤醒定时器设置 //wksel:000,RTC/16;001,RTC/8;010,RTC/4;011,RTC/2; // 10x,ck_spre,1Hz;11x,1Hz,且cnt值增加2^16(即cnt+2^16) //注意:RTC就是RTC的时钟频率,即RTCCLK! //cnt:自动重装载值.减到0,产生中断. void RTC_Set_WakeUp(u8 wksel,u16 cnt) { //关闭RTC寄存器写保护 RTC->WPR=0xCA; RTC->WPR=0x53; RTC->CR&=~(1<<10); //关闭WAKE UP while((RTC->ISR&0X04)==0); //等待WAKE UP修改允许 RTC->CR&=~(7<<0); //清除原来的设置 RTC->CR|=wksel&0X07; //设置新的值 RTC->WUTR=cnt; //设置WAKE UP自动重装载寄存器值 RTC->ISR&=~(1<<10); //清除RTC WAKE UP的标志 RTC->CR|=1<<14; //开启WAKE UP 定时器中断 RTC->CR|=1<<10; //开启WAKE UP 定时器 RTC->WPR=0XFF; //禁止修改RTC寄存器 EXTI->PR=1<<22; //清除LINE22上的中断标志位 EXTI->IMR|=1<<22; //开启line22上的中断 EXTI->RTSR|=1<<22; //line22上事件上升降沿触发 MY_NVIC_Init(2,2,RTC_WKUP_IRQn,2); //抢占2,子优先级2,组2 }
/******************************************************************************* 函 数 名: UART_Init 功能说明: 串口初始化 参 数: pclk2: 时钟频率(单位M) bound: 通信波特率 返 回 值: 无 *******************************************************************************/ void UART_Init(u32 pclk2, u32 bound) { RCC->APB2RSTR |= 1<<14; //复位串口1 RCC->APB2RSTR &= ~(1<<14); //停止复位 RCC->APB2ENR |= 1<<2; //使能PORTA口时钟 RCC->APB2ENR |= 1<<14; //使能串口时钟 GPIOA->CRH &= 0XFFFFF00F; GPIOA->CRH |= 0X000008B0; //IO状态设置 //波特率设置 USART1->BRR = (pclk2*1000000)/(bound); // 波特率设置 USART1->CR1 |= 0X200C; //1位停止,无校验位. USART1->CR1 |= 1<<8; //PE中断使能 USART1->CR1 |= 1<<5; //接收缓冲区非空中断使能 MY_NVIC_Init(3, 3, USART1_IRQn, 2);//组2,最低优先级 }
/********************************************************** * 函数功能 ---> 初始化IO 串口1 * 入口参数 ---> bound:波特率 * 返回数值 ---> none * 功能说明 ---> none **********************************************************/ void USART1_Init(uint32_t bound) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; #ifdef EN_USART1_RX //如果使能了接收中断 USART1->CR1 |= 1 << 8; //PE中断使能 USART1->CR1 |= 1 << 5; //接收缓冲区非空中断使能 MY_NVIC_Init(3, 3, USART1_IRQn, NVIC_PriorityGroup_2); //中断分组2,最低优先级 #endif RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟 USART_DeInit(USART1); //复位串口1 //USART1_TX PA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9 //USART1_RX PA.10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10 //USART 初始化设置 USART_InitStructure.USART_BaudRate = bound; //设置波特率,一般设置为9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); //初始化串口 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断 USART_Cmd(USART1, ENABLE); //使能串口 }
//初始化IO 串口2 //pclk1:PCLK1时钟频率(Mhz) //bound:波特率 void USART3_Init(u32 pclk1,u32 bound) { RCC->APB2ENR|=1<<8; //使能PORTG口时钟 GPIOG->CRH&=0XFFFFFF0F; //IO状态设置 GPIOG->CRH|=0X00000030; //IO状态设置 RCC->APB2ENR|=1<<3; //使能PORTB口时钟 ok GPIOB->CRH&=0XFFFF00FF; //IO状态设置 PB10 PB11 ok GPIOB->CRH|=0X00008B00; //IO状态设置 ok RCC->APB1ENR|=1<<18; //使能串口时钟 ok RCC->APB1RSTR|=1<<18; //复位串口3 ok RCC->APB1RSTR&=~(1<<18);//停止复位3 ok //波特率设置 USART3->BRR=(pclk1*1000000)/(bound);// 波特率设置 ok USART3->CR1|=0X200C; //1位停止,无校验位. ok //使能接收中断 #ifdef USART3_RX_EN //如果使能了接收 ok USART3->CR1|=1<<8; //PE中断使能 ok USART3->CR1|=1<<5; //接收缓冲区非空中断使能 ok MY_NVIC_Init(1,3,USART3_IRQChannel,2);//组2,最低优先级 #endif }
void SPIx_slave_Init(void){ // IOConfig(IOBB,low,PIN5,4); // IOConfig(IOBB,low,PIN4,0xb); // IOConfig(IOAB,high,PIN15,4); // IOConfig(IOBB,low,PIN6,3); // PBout(6)=0; RCC->APB2ENR|=1<<2; //PORTA时钟使能 RCC->APB2ENR|=1<<12; //SPI1时钟使能 RCC->APB2ENR|=1<<0; //开启辅助时钟 //这里只针对SPI口初始化 // GPIOA->CRL&=0X0f0FF000; // GPIOA->CRL|=0XB0B00BBB;//PA5.6.7复用 IOConfig(IOAB,0,PIN5,0X0B); IOConfig(IOAB,0,PIN6,0X0B); IOConfig(IOAB,0,PIN7,0X0B); AFIO->MAPR&=0XFFFFFFFE; //清除MAPR的[11:10] AFIO->MAPR|=1<<0; //部分重映像,TIM3_CH2->PB5 SPI1->CR1=0; SPI1->CR1|=0<<10;//全双工模式 SPI1->CR1|=0<<9; //软件nss管理 //SPI1->CR1|=1<<8; SPI1->CR1|=0<<2; //SPI slave SPI1->CR1|=0<<11;//8bit数据格式 //对24L01要设置 CPHA=0;CPOL=0; SPI1->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1 SPI1->CR1|=1<<0; //第一个时钟的下降沿,CPHA=1 CPOL=1 SPI1->CR1|=0<<3; //Fsck=Fcpu/256 SPI1->CR1|=0<<7; //MSBfirst SPI1->CR2|=1<<6; MY_NVIC_Init(0,0,SPI1_IRQChannel,2); SPI1->CR1|=1<<6; //SPI设备使能 SPIx_SetSpeed(SPI_SPEED_256); }
//初始化IO 串口2 //pclk1:PCLK1时钟频率(Mhz) //bound:波特率 void USART2_Init(u32 pclk1,u32 bound) { RCC->APB2ENR|=1<<8; //使能PORTG口时钟 GPIOG->CRH&=0XFFFFFF0F; //IO状态设置 GPIOG->CRH|=0X00000030; //IO状态设置 RCC->APB2ENR|=1<<2; //使能PORTA口时钟 GPIOA->CRL&=0XFFFF00FF; //IO状态设置 GPIOA->CRL|=0X00008B00; //IO状态设置 RCC->APB1ENR|=1<<17; //使能串口时钟 RCC->APB1RSTR|=1<<17; //复位串口2 RCC->APB1RSTR&=~(1<<17);//停止复位 //波特率设置 USART2->BRR=(pclk1*1000000)/(bound);// 波特率设置 USART2->CR1|=0X200C; //1位停止,无校验位. USART2->CR3=1<<7; //使能串口2的DMA发送 UART_DMA_Config(DMA1_Channel7,(u32)&USART2->DR,(u32)USART2_TX_BUF);//DMA1通道7,外设为串口2,存储器为USART2_TX_BUF #ifdef USART2_RX_EN //如果使能了接收 //使能接收中断 USART2->CR1|=1<<8; //PE中断使能 USART2->CR1|=1<<5; //接收缓冲区非空中断使能 MY_NVIC_Init(2,3,USART2_IRQChannel,2);//组2,最低优先级 #endif }
//外部中断初始化函数 void Touch_Init(void) { //注意,时钟使能之后,对GPIO的操作才有效 //所以上拉之前,必须使能时钟.才能实现真正的上拉输出 RCC->APB2ENR|=1<<4; //PC时钟使能 RCC->APB2ENR|=1<<0; //开启辅助时钟 GPIOC->CRL&=0XFFFF0000;//PC0~3 GPIOC->CRL|=0X00003883; GPIOC->CRH&=0XFF0FFFFF;//PC13 GPIOC->CRH|=0X00300000;//PC13推挽输出 GPIOC->ODR|=0X200f; //PC0~3 13 全部上拉 Read_ADS(&Pen_Point.X,&Pen_Point.Y);//第一次读取初始化 MY_NVIC_Init(2,0,EXTI1_IRQChannel,2); RCC->APB2ENR|=0x01; //使能io复用时钟 AFIO->EXTICR[0]|=0X0020; //EXTI13映射到PC1 EXTI->IMR|=1<<1; //开启line1上的中断 EXTI->EMR|=1<<1; //不屏蔽line1上的事件 EXTI->FTSR|=1<<1; //line1上事件下降沿触发 #ifdef ADJ_SAVE_ENABLE AT24CXX_Init();//初始化24CXX if(Get_Adjdata())return;//已经校准 else //未校准? { LCD_Clear(WHITE);//清屏 Touch_Adjust(); //屏幕校准 Save_Adjdata(); } Get_Adjdata(); #else LCD_Clear(WHITE);//清屏 Touch_Adjust(); //屏幕校准,带自动保存 #endif // printf("Pen_Point.xfac:%f\n",Pen_Point.xfac); // printf("Pen_Point.yfac:%f\n",Pen_Point.yfac); // printf("Pen_Point.xoff:%d\n",Pen_Point.xoff); // printf("Pen_Point.yoff:%d\n",Pen_Point.yoff); }