//初始化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; //串口使能 }
//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; }
//初始化IO 串口2 //pclk1:PCLK1时钟频率(Mhz) //bound:波特率 void usart2_init(u32 pclk1,u32 bound) { float temp; u16 mantissa; u16 fraction; temp=(float)(pclk1*1000000)/(bound*16);//得到USARTDIV,OVER8设置为0 mantissa=temp; //得到整数部分 fraction=(temp-mantissa)*16; //得到小数部分,OVER8设置为0 mantissa<<=4; mantissa+=fraction; RCC->AHB1ENR|=1<<0; //使能PORTA口时钟 RCC->APB1ENR|=1<<17; //使能串口2时钟 GPIO_Set(GPIOA,PIN2|PIN3,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PU);//PA9,PA10,复用功能,上拉输出 GPIO_AF_Set(GPIOA,2,7); //PA2,AF7 GPIO_AF_Set(GPIOA,3,7); //PA3,AF7 //波特率设置 USART2->BRR=mantissa; // 波特率设置 USART2->CR1|=1<<3; //串口发送使能 USART2->CR1|=1<<13; //串口使能 }
//初始化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; }
//初始化外部SRAM void FSMC_SRAM_Init(void) { RCC->AHB1ENR|=0XF<<3; //使能PD,PE,PF,PG时钟 RCC->AHB3ENR|=1<<0; //使能FSMC时钟 GPIO_AF_Set(GPIOG,10,12); //PG10,AF12(CS放到最前面,防止复位后CS非法变低,破坏原有数据) GPIO_Set(GPIOD,(3<<0)|(3<<4)|(0XFF<<8),GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PD0,1,4,5,8~15 AF OUT GPIO_Set(GPIOE,(3<<0)|(0X1FF<<7),GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PE0,1,7~15,AF OUT GPIO_Set(GPIOF,(0X3F<<0)|(0XF<<12),GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PF0~5,12~15 GPIO_Set(GPIOG,(0X3F<<0)|PIN10,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PG0~5,10 GPIO_AF_Set(GPIOD,0,12); //PD0,AF12 GPIO_AF_Set(GPIOD,1,12); //PD1,AF12 GPIO_AF_Set(GPIOD,4,12); //PD4,AF12 GPIO_AF_Set(GPIOD,5,12); //PD5,AF12 GPIO_AF_Set(GPIOD,8,12); //PD8,AF12 GPIO_AF_Set(GPIOD,9,12); //PD9,AF12 GPIO_AF_Set(GPIOD,10,12); //PD10,AF12 GPIO_AF_Set(GPIOD,11,12); //PD11,AF12 GPIO_AF_Set(GPIOD,12,12); //PD12,AF12 GPIO_AF_Set(GPIOD,13,12); //PD13,AF12 GPIO_AF_Set(GPIOD,14,12); //PD14,AF12 GPIO_AF_Set(GPIOD,15,12); //PD15,AF12 GPIO_AF_Set(GPIOE,0,12); //PE0,AF12 GPIO_AF_Set(GPIOE,1,12); //PE1,AF12 GPIO_AF_Set(GPIOE,7,12); //PE7,AF12 GPIO_AF_Set(GPIOE,8,12); //PE8,AF12 GPIO_AF_Set(GPIOE,9,12); //PE9,AF12 GPIO_AF_Set(GPIOE,10,12); //PE10,AF12 GPIO_AF_Set(GPIOE,11,12); //PE11,AF12 GPIO_AF_Set(GPIOE,12,12); //PE12,AF12 GPIO_AF_Set(GPIOE,13,12); //PE13,AF12 GPIO_AF_Set(GPIOE,14,12); //PE14,AF12 GPIO_AF_Set(GPIOE,15,12); //PE15,AF12 GPIO_AF_Set(GPIOF,0,12); //PF0,AF12 GPIO_AF_Set(GPIOF,1,12); //PF1,AF12 GPIO_AF_Set(GPIOF,2,12); //PF2,AF12 GPIO_AF_Set(GPIOF,3,12); //PF3,AF12 GPIO_AF_Set(GPIOF,4,12); //PF4,AF12 GPIO_AF_Set(GPIOF,5,12); //PF5,AF12 GPIO_AF_Set(GPIOF,12,12); //PF12,AF12 GPIO_AF_Set(GPIOF,13,12); //PF13,AF12 GPIO_AF_Set(GPIOF,14,12); //PF14,AF12 GPIO_AF_Set(GPIOF,15,12); //PF15,AF12 GPIO_AF_Set(GPIOG,0,12); //PG0,AF12 GPIO_AF_Set(GPIOG,1,12); //PG1,AF12 GPIO_AF_Set(GPIOG,2,12); //PG2,AF12 GPIO_AF_Set(GPIOG,3,12); //PG3,AF12 GPIO_AF_Set(GPIOG,4,12); //PG4,AF12 GPIO_AF_Set(GPIOG,5,12); //PG5,AF12 //寄存器清零 //bank1有NE1~4,每一个有一个BCR+TCR,所以总共八个寄存器。 //这里我们使用NE3 ,也就对应BTCR[4],[5]。 FSMC_Bank1->BTCR[4]=0X00000000; FSMC_Bank1->BTCR[5]=0X00000000; FSMC_Bank1E->BWTR[4]=0X00000000; //操作BCR寄存器 使用异步模式,模式A(读写共用一个时序寄存器) //BTCR[偶数]:BCR寄存器;BTCR[奇数]:BTR寄存器 FSMC_Bank1->BTCR[4]|=1<<12;//存储器写使能 FSMC_Bank1->BTCR[4]|=1<<4; //存储器数据宽度为16bit //操作BTR寄存器 (HCLK=168M, 1个HCLK=6ns FSMC_Bank1->BTCR[5]|=8<<8; //数据保持时间(DATAST)为9个HCLK 6*9=54ns FSMC_Bank1->BTCR[5]|=0<<4; //地址保持时间(ADDHLD)未用到 FSMC_Bank1->BTCR[5]|=0<<0; //地址建立时间(ADDSET)为0个HCLK 0ns //闪存写时序寄存器 FSMC_Bank1E->BWTR[4]=0x0FFFFFFF;//默认值 //使能BANK1区域3 FSMC_Bank1->BTCR[4]|=1<<0; }
//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 }