STM32端口复用和重映射
- 格式:doc
- 大小:109.00 KB
- 文档页数:4
STM32单片机的重映射与地址映射的使用方法及步骤重映射STM32中对于一些端口的外设已经被其他引脚所使用,这是就需要用端口重映射来解决了,很方便。
以USART1为例重映射的步骤为:打开重映射时钟和USART重映射后的I/O口引脚时钟,RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);I/O口重映射开启。
GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);配制重映射引脚,这里只需配置重映射后的I/O,原来的不需要去配置。
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_A F_PP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_I N_FLOATING;GPIO_Init(GPIOB,12345678这样就可以了,很简单。
地址映射对于地址映射是在查重映射时发现的,感觉ST的库很机智,就记录下来。
首先看一下M3 存储器映射我们的操作就在这512MB的地址进行。
在LED灯的程序中,存在宏定义:#defineGPIOC_BASE(APB2PERIPH_BASE+0x1000)#defineAPB2PERIPH_BASE (PERIPH_BASE+0x10000)#definePERIPH_BASE((uint32_t)0x40000000)123。
STM32的功能引脚重映射和复用功能STM32中有很多内置外设的输入输出引脚都具有重映射(remap)的功能,本文对一些在使用引脚重映射时所遇到的有关问题加以说明。
我们知道每个内置外设都有若干个输入输出引脚,一般这些引脚的输出脚位都是固定不变的,为了让设计工程师可以更好地安排引脚的走向和功能,在STM32中引入了外设引脚重映射的概念,即一个外设的引脚除了具有默认的脚位外,还可以通过设置重映射寄存器的方式,把这个外设的引脚映射到其它的脚位。
下面是STM32F103xC中有关USART3引脚的摘要片段;从这里可以看出,USART3_TX的默认引出脚是PB10,USART3_RX的默认引出脚是PB11;但经过重映射后,可以变更USART3_TX的引出脚为PD8,变更USART3_RX的引出脚为PD9。
STM32中的很多内置外设都具有重映射的功能,比如USART、定时器、CAN、SPI、I2C等,详细请看STM32参考手册(RM0008)和STM32数据手册。
有些模块(内置外设)的重映射功能还可以有多种选择,下面是RM0008上有关USART3输入输出引脚的重映射功能表:从这个表中可以看出,USART3的TX和RX引脚默认的引出脚位是PB10和PB11,根据配置位的设置,可以重映射到PC10和PC11,还可以重映射到PD8和PD9。
一个模块的功能引脚不管是从默认的脚位引出还是从重映射的脚位引出,都要通过GPIO端口模块实现,相应的GPIO端口必须配置为输入(对应模块的输入功能,如USART的RX)或复用输出(对应模块的输出功能,如USART的TX),对于输出引脚,可以按照需要配置为推挽复用输出或开漏复用输出。
上图是STM32的GPIO端口模块,使用复用功能时的配置。
从图中可以看出,配置为复用输出时,该端口对应的GPIO输出功能将不起作用。
例如当配置PB10对应的引脚为复用输出功能时,操作PB10对应的输出寄存器将不影响引脚上的信号。
STM32端口复用和端口重映射?什么是端口复用重映射?对于(单片机)而言,GPIO引脚配置是最基本的,也是最重要的,因为所有的((信号))输入和(控制)输出都是通过这些配置起作用的。
这里就不得不提到单片机的复用功能AF(Al(te)rnate Func(ti)on),这篇文章我们说一说复用功能。
(STM32)Fxx系列单片机的GPIO可以配置为浮空输入(input floating)、上拉输入(input pull-up)、下拉输入(input pull-down)、(模拟)输入((analog))、开漏输出(output open-drain)、推挽输出(ouput push-pull)、复用开漏输出(alternate function open-drain)、复用推挽输出(alternate function push-pull)等8种模式。
先说明一下开漏输出和推挽输出的区别。
STM32Fxx系列单片机的输出电路由两个MOS管,分别是P-MOS 和N-MOS。
在开漏输出模式下,P-MOS管不工作,只有N-MOS管工作。
若输入数据(寄存器)的值为0,则N-MOS导通,IO口输出低电平;若输出数据寄存器的值为1,则N-MOS截止;由于P-MOS不工作,此时IO口既不是高电平,也不是低电平,这种状态被称为高阻态。
STM32F1xx IO口基本结构在推挽输出模式下,若输出数据寄存器的值为0,则N-MOS导通,P-MOS截止,IO口输出低电平;若输出数据寄存器的值为1,则N-MOS截止,P-MOS导通,IO口输出高电平。
上面提到了STM32Fxx系列单片机还有复用开漏输出和复用推挽输出,它们和上面讲到的(通用)开漏输出和(普通)推挽输出有什么区别?这就涉及到引脚复用的功能。
使用过单片机的(工程师)都了解,STM32Fxx内部集成了很多的外设(控制器),比如USART、SPI、(CAN)等,这些外设控制器,也需要通过引脚与外设连接。
STM32部分重映射和完全重映射(查看数据⼿册)
数据⼿册如何查找对应的映射:
打开官⽹直接搜索STM32F可以看到数据⼿册,⾥⾯有关于,输⼊第6页的页码,点击9.3中的9.3x可打开对应的链接。
举例说明:
STM32中拥有重映射功能,可以使硬件电路的设计更加简洁⽅便,在配置GPIO_PinRemapConfig()函数时,发现⼊⼝参数有两种重映射,分为部分重映射(Partial Remap)和完全重映射(Full Remap),那么这两个有什么区别呢?
标题以TIM3为例
根据图⽚可以看到,TIM3的部分重映射和完全重映射对应的引脚是不同的,所以在配置选择部分重映射和完全重映射的时候要考虑⼀下。
重映射引脚分配图在哪
这⼀部分其实并不在STM32的数据⼿册中,⽽在STM32的官⽅⼿册的8.3节,⾥⾯有所有功能的引脚分配情况。
如何配置STM32F103的重映射USART分类:学习笔记2012-12-26 10:18 136人阅读评论(0) 收藏举报STM32stm32USART重映射这两天用STM32F103操作MC39i,其中用到STM32的重映射串口3,部分重映射到PC10、PC11上。
经参考了正点原子的《STM32不完全手册》并查看手册,调试成功讲解如下,如有不足欢迎指正。
经查找手册见下图:此时配置串口步骤如下:1.开启辅助时钟:RCC->APB2ENR|=1<<0;2.配置重映射寄存器,请串口3部分映射到PC口上:AFIO->MAPR|=1<<4;//USART3_REMAP[1:0]=0B01;3.使能PC口和串口:RCC->APB2ENR|=1<<4; //使能PORTC口时钟RCC->APB1ENR|=1<<18; //使能串口时钟4.配置IO口的状态:GPIOC->CRH=0X44444B44;//IO状态设置PC10/PC115.复位串口:RCC->APB1RSTR|=1<<18; //复位串口1RCC->APB1RSTR&=~(1<<18);//停止复位6.设置波特率和传输方式:USART3->BRR、USART3->CR1。
7.配置接受中断和中的优先级:USART3->CR1|=1<<8; //PE中断使能USART3->CR1|=1<<5; //接收缓冲区非空中断使能MY_NVIC_Init(2,3,USART1_IRQChannel,2);//组2,最低优先级至此配置完成。
备注:串口管脚配置见下图。
STM32的SPI1引脚重映射初次使用STM32有些不太明白,此次调试经验奉献出来与大家分享!系统:STM32 + SD + FA TFSSTM32与SD卡的连接如下定义,PB口#define SD_SCK GPIO_Pin_3#define SD_MISO GPIO_Pin_4#define SD_MOSI GPIO_Pin_5#define SD_CS GPIO_Pin_7我想使用SPI1并重映射引脚使用时注意的事项如下:1.使能PB0时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);2.使能AFIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);3.使能SPI1时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 , ENABLE);4.禁用JTAG时钟复用 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);5.SPI1引脚重映射 GPIO_PinRemapConfig(GPIO_Remap_SPI1,ENABLE);接着初始化GPIO和SPI1即可,如:void SpiOpen(void){GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef SPI_InitStructure;/* Configure SPI1 pins: SCKand MOSI */GPIO_InitStructure.GPIO_Pin = SD_MOSI|SD_SCK|SD_MISO;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);/* Configure PB7 pin: CS pin */GPIO_InitStructure.GPIO_Pin = SD_CS;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB,SD_CS);/* SPI1 Config */SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 7;SPI_Init(SPI1, &SPI_InitStructure);/* SPI1 enable */SPI_Cmd(SPI1, ENABLE);}可是这一切完成的时候结果却与想象的不同,无法在SD卡内创建文件,找一个晚上没有结果不得已采用另一种方法:软件模拟SPI测试了一下,结果另人出呼意料,一次搞定,没有任何问题,但为了效率还是希望使用硬SPI口,于是从引脚重映射上寻找原因又费了一晚上无果第三个晚上:经过无数次的改动 + 测试终于OK了,问题出在哪里了呢?原来SD卡的初始时钟不一定是<400KHz就行ST标准库初始化系统时APB2时钟为72MHz,经过256分频波特率约等于280KHz(SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;)对于我测试用的SD卡这个速度仍太快,于是降APB2时钟进行测试,OK!RCC_PCLK2Config(RCC_HCLK_Div4); //72/4=18MHz仅仅是一行代码,这就是初学代价!,哈哈.另外要说明的是,在MISO引脚上加了一个22k上接电阻.代码://#define USE_SOFT_SPI#ifdef USE_SOFT_SPIBYTE g_SPISpeedFlag=0;static void delay_bus(void){unsigned int i=100;if(g_SPISpeedFlag) //高速模式 < 25MHzi=10;while(--i) //低速模式 < 400KHz__nop();}void SpiOpen(void){//IO初始化用结构体GPIO_InitTypeDef GPIO_InitStructure;//输出引脚初始化GPIO_InitStructure.GPIO_Pin=SD_SCK|SD_CS|SD_MOSI;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);//输入引脚配置GPIO_InitStructure.GPIO_Pin=SD_MISO;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//GPIO_Mode_IN_FLOATING ; GPIO_Init(GPIOB, &GPIO_InitStructure);//设置端口初始电平GPIO_SetBits(GPIOB,SD_CS);GPIO_SetBits(GPIOB,SD_SCK);g_SPISpeedFlag=0;}void SpiClose(void){GPIO_SetBits(GPIOB,SD_CS);GPIO_SetBits(GPIOB,SD_SCK);Stat &= ~STA_NOINIT;}void SPI_SetHeighSpeed(void){g_SPISpeedFlag=1;}BYTE SPI_ReadWriteByte(BYTE outgoing){uint32_t i;uint8_t ret=0;delay_bus();for(i=0;i<8;i++){ret<<=1;if(outgoing &0x80) //主设备锁存数据GPIO_SetBits(GPIOB,SD_MOSI);elseGPIO_ResetBits(GPIOB,SD_MOSI);GPIO_ResetBits(GPIOB,SD_SCK); //产生第一个时钟沿,让从设备也在此时锁存数据 delay_bus();if(GPIO_ReadInputDataBit(GPIOB,SD_MISO)) //主设备采样ret|=1;GPIO_SetBits(GPIOB,SD_SCK); //产生第二个时钟沿,让从设备也在此时采样delay_bus();outgoing<<=1;}return ret;}#else //硬件SPI 使用SPI1引脚重映射void SpiOpen(void){GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef SPI_InitStructure;GPIO_PinRemapConfig(GPIO_Remap_SPI1,ENABLE);/* Configure SPI1 pins: SCKand MOSI */GPIO_InitStructure.GPIO_Pin = SD_MOSI|SD_SCK|SD_MISO;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);/* Configure PB7 pin: CS pin */GPIO_InitStructure.GPIO_Pin = SD_CS;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB,SD_CS);/* SPI1 Config */SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 7;SPI_Init(SPI1, &SPI_InitStructure);/* SPI1 enable */SPI_Cmd(SPI1, ENABLE);}void SpiClose(void){SPI_Cmd(SPI1, DISABLE);Stat &= ~STA_NOINIT;}void SPI_SetHeighSpeed(void){SPI_InitTypeDef SPI_InitStructure;/* SPI1 Config */SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 7;SPI_Init(SPI1, &SPI_InitStructure);SPI_Cmd(SPI1, ENABLE);}BYTE SPI_ReadWriteByte(BYTE outgoing){/* Loop while DR register in not emplty */while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);/* Send byte through the SPI1 peripheral */SPI_I2S_SendData(SPI1, outgoing);/* Wait to receive a byte */while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);/* Return the byte read from the SPI bus */return SPI_I2S_ReceiveData(SPI1);}#endif。
STM32功能引脚端口复用和重映射
在STM32系列微控制器中,每个引脚都有一个默认的功能。
通过端口复用,我们可以将一个引脚的默认功能改变为其他的功能。
每个引脚都有一个对应的功能选择字,可以通过设置这个字来实现不同的功能。
引脚的功能可以是GPIO输入输出、模拟输入输出、定时器输入输出、串行通信等等。
端口复用功能使我们可以在同一个引脚上实现多种不同功能的选择。
比如,一个IO引脚默认是用作GPIO输入输出的,可以通过端口复用将其改为定时器的输入或输出引脚,实现定时器功能。
在一些情况下,系统的引脚数量有限,无法满足需求,此时就可以使用引脚重映射来实现更多的功能。
引脚重映射是将一个引脚的默认功能映射到其他引脚上,可以实现多个引脚共享一个功能。
引脚重映射需要特定的硬件支持,不是所有引脚都支持重映射。
可以通过引脚映射寄存器来设置引脚重映射。
引脚重映射的功能让系统设计更加灵活和可扩展。
在一个引脚只能实现一个功能的情况下,通过重映射可以将多个引脚的功能映射到一个引脚上,实现多个功能的共享。
端口复用和重映射的具体实现方式和寄存器设置是根据不同型号的STM32微控制器而有所不同的。
在开发过程中,需要查阅相关的文档和手册,了解具体的端口复用和重映射的功能和设置方法。
总之,STM32微控制器的功能引脚可以通过端口复用和重映射实现多种不同的功能。
端口复用可以改变引脚的默认功能,而重映射可以实现多个引脚共享一个功能。
这些功能增强了系统的灵活性和可扩展性。
在实际
应用中,需要根据具体需求选择适当的引脚复用和重映射方式,以满足系统的需求。
stm32的TIM2的端口使用组合有下面四种:1.当不重映射时,默认TIM2四个的IO口是PA0、PA1、PA2、PA32.要使用PA15、PB3、PA2、PA3的端口组合,要调用下面的语句进行部分重映射:RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //重映射必须要开AFIO时钟GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);3.要使用PA0、PA1、PB10、PB11的端口组合,要调用下面的语句进行部分重映射:RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //重映射必须要开AFIO时钟GPIO_PinRemapConfig(GPIO_PartialRemap2_TIM2, ENABLE);4.要使用PA15、PB3、PB10、PB11的端口组合,要调用下面的语句进行完全重映射:RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //重映射必须要开AFIO时钟GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE);同时还要禁用JTAG功能,PA15、PB3、PB10、PB11才会正常输出。
GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE);/**********************1.执行端口重映射时,复用功能时钟得使能:RCC_APB2Periph_AFIO2. 1. GPIO_Remap_SWJ_Disable: !< Full SWJ Disabled (JTAG-DP + SW-DP)此时PA13|PA14|PA15|PB3|PB4都可作为普通IO用了为了保存某些调试端口,GPIO_Remap_SWJ_Disable也可选择为下面两种模式:2. GPIO_Remap_SWJ_JTAGDisable: !< JTAG-DP Disabled and SW-DP Enabled此时PA15|PB3|PB4可作为普通IO用了3. GPIO_Remap_SWJ_NoJTRST: !< Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST此时只有PB4可作为普通IO用了**********************/GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST, ENABLE); //使能禁止JTAGGPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE); //JATG-DP禁用,但是SW-DP可使用//初始化GPIOB 推挽输出GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_3|GPIO_Pin_4);GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB, GPIO_Pin_3|GPIO_Pin_4);//初始化GPIOA 推挽输出GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_SetBits(GPIOA, GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);。
STM32的CAN现场总线应用总结CAN现场总线的应用最重要的就是其接口端口映射、初始化及数据的发送、接收。
STM32中的CAN物理引脚可以设置成三种:默认模式、重定义地址1模式、重定义地址2模式。
CAN信号可以被映射到端口A、端口B或端口D上,如下表所示,对于端口D,在36、48和64脚的封装上没有重映射功能。
重映射不适用于36脚的封装当PD0和PD1没有被重映射到OSC_IN和OSC_OUT时,重映射功能只适用于100脚和144脚的封装上---------------------------------------------------------------------------------------------------------------------- 默认模式/* Configure CAN pin: RX */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(GPIO_CAN_Key, &GPIO_InitStructure);/* Configure CAN pin: TX */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);---------------------------------------------------------------------------------------------------------------------- 重定义地址1模式/* Configure CAN pin: RX */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(GPIO_CAN_Key, &GPIO_InitStructure);/* Configure CAN pin: TX */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIO_CAN_Key, &GPIO_InitStructure);/*Configure CAN Remap 重映射*/GPIO_PinRemapConfig(GPIO_Remap1_CAN,ENABLE);---------------------------------------------------------------------------------------------------------------------- /* Configure CAN pin: RX */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIO_CAN_Key, &GPIO_InitStructure);/* Configure CAN pin: TX */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIO_CAN_Key, &GPIO_InitStructure);/*Configure CAN Remap 重映射 */GPIO_PinRemapConfig(GPIO_Remap2_CAN,ENABLE);---------------------------------------------------------------------------------------------------------------------- 设置完CAN 的引脚之后还需要打开CAN 的时钟: /* CAN Periph clock enable */RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN,ENABLE); 2. 初始化2.1.1 CAN 单元初始化CAN 单元初始化最重要的就是波特率的设置,原理如下:t波特率=1/位时间位时间 = (1 + t BS1 + t BS2)× t q t q = t PCLKt PCLK = APB1例如现有一STM32系统时钟为72MHz ,关于CAN 波特率有以下设置: CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; //重新同步跳跃宽度1个时间单位 CAN_InitStructure.CAN_BS1 = CAN_BS1_8tq; //时间段1为8个时间单位 CAN_InitStructure.CAN_BS2 = CAN_BS2_7tq; //时间段2为7个时间单位 CAN_InitStructure.CAN_Prescaler = 45; //设定了一个时间单位的长度为45则其CAN 的波特率为1÷[(1+8+7)×456CAN 以外还包括以下设置:CAN_InitTypeDef CAN_InitStructure; //定义一个CAN 单元CAN_InitStructure.CAN_TTCM = DISABLE; //设置时间触发通信模式(失能) CAN_InitStructure.CAN_ABOM = DISABLE;// 使/失能自动离线管理(失能) CAN_InitStructure.CAN_AWUM = DISABLE;// 使/失能自动唤醒模式(失能) CAN_InitStructure.CAN_NART = DISABLE; //使/失能非自动重传输模式(失能) CAN_InitStructure.CAN_RFLM = DISABLE;// 使/失能接收FIFO 锁定模式(失能) CAN_InitStructure.CAN_TXFP = DISABLE; //使/失能发送FIFO 优先级(失能)CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;//设置CAN 工作模式(正常模式) 2.1.2 CAN 报文过滤器初始化STM32共有14组过滤器,每组过滤器包括了2个可配置的32位寄存器:CAN_FxR0和CAN_FxR1。
STM32的功能引脚重映射和复用功能
STM32中有很多内置外设的输入输出引脚都具有重映射(remap)的功能,本文对一些在使用引脚重映射时所遇到的有关问题加以说明。
我们知道每个内置外设都有若干个输入输出引脚,一般这些引脚的输出脚位都是固定不变的,为了让设计工程师可以更好地安排引脚的走向和功能,在STM32中引入了外设引脚重映射的概念,即一个外设的引脚除了具有默认的脚位外,还可以通过设置重映射寄存器的方式,把这个外设的引脚映射到其它的脚位。
下面是STM32F103xC中有关USART3引脚的摘要片段;
USART3_TX的默认引出脚是PB10,USART3_RX的默认引出脚是PB11;但经过重映射后,可以变更USART3_TX的引出脚为PD8,变更USART3_RX的引出脚为PD9。
STM32中的很多内置外设都具有重映射的功能,比如USART、定时器、CAN、SPI、I2C等,详细请看STM32参考手册(RM0008)和STM32数据手册。
有些模块(内置外设)的重映射功能还可以有多种选择,下面是RM0008上有关USART3输入输出引脚的重映射功能表:
从这个表中可以看出,USART3的TX和RX引脚默认的引出脚位是PB10和PB11,根据配置位的设置,可以重映射到PC10和PC11,还可以重映射到PD8和PD9。
一个模块的功能引脚不管是从默认的脚位引出还是从重映射的脚位引出,都要通过GPIO端口模块实现,相应的GPIO端口必须配置为输入(对应模块的输入功能,如USART的RX)或复用输出(对应模块的输出功能,如USART的TX),对于输出引脚,可以按照需要配置为推挽复用输出或开漏复用输出。
上图是STM32的GPIO端口模块,使用复用功能时的配置。
从图中可以看出,配置为复用输出时,该端口对应的GPIO输出功能将不起作用。
例如当配置PB10对应的引脚为复用输出功能时,操作PB10对应的输出寄存器将不影响引脚上的信号。
从图中还可以看出,普通的GPIO端口输入功能与复用的输入功能的配置方式没有分别,这意味着在使用引脚的复用输入功能时,可以在这个引脚的输入寄存器上读出引脚上的信号。
例如在使能了USART3模块时,可以读GPIOB_IDR 寄存器,得到PB11信号线上的当前状态。
有不少引脚上配备了来自多个模块的复用功能引出脚,例如本文第一张图中显示的PB10,默认复用功能就有I2C2_SCL和USART3_TX两个功能,TIM2重映射后,TIM2_CH3也使用PB10的复用功能。
在使用引脚的复用功能时,需要注意在软件上只可以使能一个外设模块,否则在引出脚上可能产生信号冲突。
例如,如果使能了USART3模块,同时没有对USART3进行重映射配置,则不可以使能I2C2模块;同理如果需要使用I2C2模块,则不能使能USART3模块。
但是如果配置了USART3的引脚重映射,USART3的TX和RX信号将从PC10和PC11,或PD8和PD9引出,避开了I2C2使用的PB10和PB11,这时就可以同时使用I2C2模块和USART3模块了。
USART3模块共有5个信号,分别为TX、RX、CK、CTS和RTS,从上面给出的第二张图中可以看出,重映射是对所有信号同时有效。
这5个信号中,在使能了USART3模块后,只有TX和RX是始终与对应的引出脚相连,而其它3个信号分别有独立的控制位,控制它们是否与外部引脚相连,如果程序中不使用某个信号的功能,则可以关闭这个信号的功能,对应的引脚可以做为其它功能的引出脚。
例如,当关闭了USART3的CK、CTS和RTS 功能并且没有重映射USART3时,PB12、PB13和PB14可以作为通用输入输出端口使用,也可以作为其它模块的复用功能引出脚。
下面这张图是一个内部控制连接的等效示意图,它并不表示真正的内部连接,但可以有效地帮助理解重映射和复用引脚的概念。
图中右边引出的信号,分别连接到了本文第三张图的输入输出模块。