STM32笔记—stm32F105RB 使用总结
一、硬件
stm32F105 最小系统
二、软件
1、晶振
STM32F105RB 默认晶振25M ,而在使用的过程中,我这边使用的是8M的晶振 ,所以需要修改两个地方
1)在stm32f10x.h头文件中把HSE_VALUE值修改为你实际晶振的值,例如修改为8000000;
2)在system_stmf10x.c中
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL2 configuration: PLL2CLK = (HSE / 8) * 8 = 8 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 1 = 8 MHz */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV8 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV1);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL9);
2、stm32F105的时钟树
3、在程序中获取系统的时钟
只需要在int main(), 初始化时 加入两行代码就可以获取各个时钟,之后仿真打印。 需要添加的代码:
RCC_ClocksTypeDef get_rcc_clock; //获取系统时钟状态
RCC_GetClocksFreq(&get_rcc_clock); //仿真的时候就可以在结构体get_rcc_clock中看见各个外设的时钟了
仿真打印结果
4、stm32F105CAN 双CAN 驱动;
1、GPIO 配置
void CAN1_PinInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*外设时钟设置*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO |RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
/* Configure CAN pin: RX */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure CAN pin: TX */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void CAN2_PinInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*外设时钟设置*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);
/* Configure CAN pin: RX */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure CAN pin: TX */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
2、双can 配置
void CAN1_Configuration(void)
{
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
// CAN register init
CAN_DeInit(CAN1);
CAN_StructInit(&CAN_InitStructure);
// CAN cell init DISABLE=0,ENABLE=1
CAN_InitStructure.CAN_TTCM=DISABLE;//禁止时间触发通信模式
CAN_InitStructure.CAN_ABOM=DISABLE;//自动离线恢复
CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过清除sleep位来唤醒
CAN_InitStructure.CAN_NART=ENABLE;//DISABLE;报文自动重传
CAN_InitStructure.CAN_RFLM=DISABLE;//接收溢出时,FIFO未锁定
CAN_InitStructure.CAN_TXFP=DISABLE;//发送的优先级由标示符的大小决定
CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;//正常模式下
//设置can通讯波特率为1000kbps
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
CAN_InitStructure.CAN_BS1=CAN_BS1_4tq;
CAN_InitStructure.CAN_BS2=CAN_BS2_4tq;
CAN_InitStructure.CAN_Prescaler=4;
// CAN_Mode_Init( CAN_SJW_1tq,CAN_BS2_4tq,CAN_BS2_3tq,4,0); // CAN 初始化 1M
CAN_Init(CAN1,&CAN_InitStructure);
// CAN filter init
CAN_FilterInitStructure.CAN_FilterNumber=0;
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; /* 屏敝模式 */
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//CAN_FilterScale_16bit; //32bit
CAN_FilterInitStructure.CAN_FilterIdHigh= (((FlTA1)<<21)&0xFFFF0000)>>16;
CAN_FilterInitStructure.CAN_FilterIdLow= (((FlTA1)<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000; //
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000; //
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //时能过滤器
CAN_FilterInit(&CAN_FilterInitStructure);
/*CAN通信中断使能*/
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
}
void CAN2_Configuration(void)
{
// CAN_ITConfig(CAN1, CAN_IT_FMP1, ENABLE);
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
// CAN register init
CAN_DeInit(CAN2);
CAN_StructInit(&CAN_InitStructure);
// CAN cell init
CAN_InitStructure.CAN_TTCM=DISABLE;//禁止时间触发通信模式
CAN_InitStructure.CAN_ABOM=DISABLE;//自动离线恢复
CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过清除sleep位来唤醒
CAN_InitStructure.CAN_NART=ENABLE;//DISABLE;报文自动重传
CAN_InitStructure.CAN_RFLM=DISABLE;//接收溢出时,FIFO未锁定
CAN_InitStructure.CAN_TXFP=DISABLE;//发送的优先级由标示符的大小决定
CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;//正常模式下
// CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;//正常模式下 CAN_Mode_LoopBack
//设置can通讯波特率为1000kbps
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
CAN_InitStructure.CAN_BS1=CAN_BS1_4tq;
CAN_InitStructure.CAN_BS2=CAN_BS2_4tq;
CAN_InitStructure.CAN_Prescaler=4;
CAN_Init(CAN2,&CAN_InitStructure);
CAN_FilterInitStructure.CAN_FilterNumber=14; /* 过滤器14 */
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; /* 屏敝模式 */
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//CAN_FilterScale_16bit; //32bit
CAN_FilterInitStructure.CAN_FilterIdHigh= ((FlTA2<<21)&0xffff0000)>>16;32位ID
CAN_FilterInitStructure.CAN_FilterIdLow= ((FlTA2<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xffff;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000; //
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000; //
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO1;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //使能过滤器
CAN_FilterInit(&CAN_FilterInitStructure);
CAN_ITConfig(CAN2, CAN_IT_FMP1, ENABLE);
CAN_ITConfig(CAN2,CAN_IT_TME,ENABLE);
CAN_ITConfig(CAN2,CAN_IT_BOF,ENABLE);
} 3、NVIC 配置
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/*中断设置*/
NVIC_InitStructure.NVIC_IRQChannel =CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel =CAN2_RX1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
4、CAN 发送
void CAN_Send_Msg(u8* msg,u8 len)
{
u16 i=0;u8 mbox;
CanTxMsg TxMessage;
TxMessage.StdId=0x000; // 标准标识符为0
TxMessage.ExtId=0x12; // 设置扩展标示符(29位)
TxMessage.IDE=CAN_ID_STD; // 使用扩展标识符
TxMessage.RTR=CAN_RTR_Data; // 消息类型为数据帧,一帧8位
TxMessage.DLC=len; // 发送两帧信息
for(i=0;i<len;i++)
TxMessage.Data[i]=*(msg+i); // 第一帧信息
mbox= CAN_Transmit(CAN1, &TxMessage);
i=0;
while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)); //等待发送结束
while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++; //等待发送结束
}
5、CAN接收
void CAN1_RX0_IRQHandler(void)
{
if(CAN_GetITStatus(CAN1,CAN_IT_TME)!= RESET)
{
CAN_ClearITPendingBit(CAN1,CAN_IT_TME);
}
CAN_Receive(CAN1, 0, &RxMessage);
}
void CAN2_RX1_IRQHandler(void)
{
if(CAN_GetITStatus(CAN2,CAN_IT_TME)!= RESET)
{
CAN_ClearITPendingBit(CAN2,CAN_IT_TME);
}
CAN_Receive(CAN2, 0, &RxMessage);
}
在调试CAN 芯片时,需要注意 1、硬件 CAN芯片是都在工作,可以测量CAN芯片的VCC ,CANH,CANL,. 2、软件 CAN 被配置程过滤模式后,检查FlTA1、 FlTA2 设置是都对。 另外调试CAN时,尽量搭配CAN盒一块调试。
上面笔记有些内容是参考网上的一些资料,具体的详细链接已记不清了,资料仅供学习用。
|