STM32 CAN通信 滤波器配置总结

发布者:温馨生活最新更新时间:2016-09-27 来源: eefocus关键字:STM32  CAN通信  滤波器 手机看文章 扫描二维码
随时随地手机看文章
首先声明stm32手册写的太蛋疼,让我看了好长时间没看懂,后来根据实践再回头看了,才看懂一些,在这里还要感激网友发表的博客,下面内容为转载:

一、在STM32互联型产品中,CAN1和CAN2分享28个过滤器组,其它STM32F103xx系列产品中有14个过滤器组,用以对接收到的帧进行过滤。

每组过滤器包括了2个可配置的32位寄存器:CAN_FxR0和CAN_FxR1。这些过滤器相当于关卡,每当收到一条报文时,CAN要先将收到的报文从这些过滤器上"过"一下,能通过的报文是有效报文,收进相关联FIFO(FIFO1或FIFO2),不能通过的是无效报文(不是发给"我"的报文),直接丢弃。 

    (标准CAN的标志长度是11位。扩展格式CAN的标志长度是29。CAN2.0A协议规定CAN控制器必须有一个11位的标识符。CAN2.0B协议中规定CAN控制器的标示符长度可以是11位或29位。STM32同时支持CAN2.0A/CAN2.0B协议。)    

STM32 CAN通信 滤波器配置总结 - likang0110 - likang0110的博客

STM32 CAN通信 滤波器配置总结 - likang0110 - likang0110的博客

 

    每组过滤器组有两种工作模式:标识符列表模式和标识符屏蔽位模式。

标识符屏蔽位模式:可过滤出一组标识符。此时,这样CAN_FxR0中保存的就是标识符匹配值,CAN_FxR1中保存的是屏蔽码,即CAN_FxR1中如果某一位为1,则CAN_FxR0中相应的位必须与收到的帧的标志符中的相应位吻合才能通过过滤器;CAN_FxR1中为0的位表示CAN_FxR0中的相应位可不必与收到的帧进行匹配。

标识符列表模式:可过滤出一个标识。此时CAN_FxR0和CAN_FxR1中的都是要匹配的标识符,收到的帧的标识符必须与其中的一个吻合才能通过过滤。

     注意:CAN_FilterIdHigh是指高16位CAN_FilterIdLow是低16位应该将需要得到的帧的和过滤器的设置值左对齐起。

     所有的过滤器是并联的,即一个报文只要通过了一个过滤器,就是算是有效的。 

按工作模式和宽度,一个过滤器组可以变成以下几中形式之一:
(1) 1个32位的屏蔽位模式的过滤器。
(2) 2个32位的列表模式的过滤器。
(3) 2个16位的屏蔽位模式的过滤器。
(4) 4个16位的列表模式的过滤器。

每组过滤器组有两个32位的寄存器用于存储过滤用的"标准值",分别是FxR1,FxR2。
在32位的屏蔽位模式下:
    有1个过滤器。
    FxR2用于指定需要关心哪些位,FxR1用于指定这些位的标准值。
在32位的列表模式下:
    有两个过滤器。
    FxR1指定过滤器0的标准值FxR2指定过滤器1的标准值。

收到报文的标识符只有跟FxR1与FxR1其中的一个完全相同时,才算通过。
在16位的屏蔽位模式下:
    有2个过滤器。
    FxR1配置过滤器0,其中,[31-16]位指定要关心的位,[15-0]位指定这些位的标准值。
    FxR2配置过滤器1,其中,[31-16]位指定要关心的位,[15-0]位指定这些位的标准值。
在16位的列表模式下:
    有4个过滤器。
    FxR1的[15-0]位配置过滤器0,FxR1的[31-16]位配置过滤器1。
    FxR2的[15-0]位配置过滤器2,FxR2的[31-16]位配置过滤器3。

 

STM32的CAN有两个FIFO,分别是FIFO0和FIFO1。为了便于区分,下面FIFO0写作FIFO_0,FIFO1写作FIFO_1。
每组过滤器组必须关联且只能关联一个FIFO。复位默认都关联到FIFO_0。
所谓“关联”是指假如收到的报文从某个过滤器通过了,那么该报文会被存到该过滤器相连的FIFO。
从另一方面来说,每个FIFO都关联了一串的过滤器组,两个FIFO刚好瓜分了所有的过滤器组。

 每当收到一个报文,CAN就将这个报文先与FIFO_0关联的过滤器比较,如果被匹配,就将此报文放入FIFO_0中。
如果不匹配,再将报文与FIFO_1关联的过滤器比较,如果被匹配,该报文就放入FIFO_1中。
如果还是不匹配,此报文就被丢弃。

每个FIFO的所有过滤器都是并联的,只要通过了其中任何一个过滤器,该报文就有效。
如果一个报文既符合FIFO_0的规定,又符合FIFO_1的规定,显然,根据操作顺序,它只会放到FIFO_0中。

每个FIFO中只有激活了的过滤器才起作用,换句话说,如果一个FIFO有20个过滤器,但是只激话了5个,那么比较报文时,只拿这5个过滤器作比较。
一般要用到某个过滤器时,在初始化阶段就直接将它激活。
需要注意的是,每个FIFO必须至少激活一个过滤器,它才有可能收到报文。如果一个过滤器都没有激活,那么是所有报文都报废的。
一般的,如果不想用复杂的过滤功能,FIFO可以只激活一组过滤器组,且将它设置成32位的屏蔽位模式,两个标准值寄存器(FxR1,FxR2)都设置成0。这样所有报文均能通过。(STM32提供的例程里就是这么做的!)

STM32 CAN中,另一个较难理解的就是过滤器编号。
过滤器编号用于加速CPU对收到报文的处理。
收到一个有效报文时, CAN会将收到的报文 以及它所通过的过滤器编号, 一起存入接收邮箱中。CPU在处理时,可以根据过滤器编号,快速的知道该报文的用途,从而作出相应处理。
不用过滤器编号其实也是可以的, 这时候CPU就要分析所收报文的标识符, 从而知道报文的用途。
由于标识符所含的信息较多,处理起来就慢一点了。

STM32使用以下规则对过滤器编号:
(1) FIFO_0和FIFO_1的过滤器分别独立编号,均从0开始按顺序编号。
(2) 所有关联同一个FIFO的过滤器,不管有没有被激活,均统一进行编号。
(3) 编号从0开始,按过滤器组的编号从小到大,按顺序排列。
(4) 在同一过滤器组内,按寄存器从小到大编号。FxR1配置的过滤器编号小,FxR2配置的过滤器编号大。
(5) 同一个寄存器内,按位序从小到大编号。[15-0]位配置的过滤器编号小,[31-16]位配置的过滤器编号大。
(6) 过滤器编号是弹性的。 当更改了设置时,每个过滤器的编号都会改变。
    但是在设置不变的情况下,各个过滤器的编号是相对稳定的。

这样,每个过滤器在自己在FIFO中都有编号。
在FIFO_0中,编号从0 -- (M-1), 其中M为它的过滤器总数。
在FIFO_1中,编号从0 -- (N-1),,其中N为它的过滤器总数。

一个FIFO如果有很多的过滤器,,可能会有一条报文, 在几个过滤器上均能通过,这时候,,这条报文算是从哪儿过来的呢?
STM32在使用过滤器时,按以下顺序进行过滤:
(1) 位宽为32位的过滤器,优先级高于位宽为16位的过滤器。
(2) 对于位宽相同的过滤器,标识符列表模式的优先级高于屏蔽位模式。
(3) 位宽和模式都相同的过滤器,优先级由过滤器号决定,过滤器号小的优先级高。

按这样的顺序,报文能通过的第一个过滤器,就是该报文的过滤器编号,被存入接收邮箱中。

二、下面是我的代码:

 


 

/*时钟初始化*/

void RCC_Configuration(void)
{
    ErrorStatus HSEStartUpStatus;
 // RCC system reset(for debug purpose)
    RCC_DeInit();

    // Enable HSE  
    RCC_HSEConfig(RCC_HSE_ON);

 //Enable HSI for Flash Operation
 RCC_HSICmd(ENABLE);

    // Wait till HSE is ready
    HSEStartUpStatus = RCC_WaitForHSEStartUp();

    if(HSEStartUpStatus == SUCCESS)
    {
        // HCLK = SYSCLK     AHB时钟为系统时钟  72MHz
        RCC_HCLKConfig(RCC_SYSCLK_Div1);

        // PCLK2 = HCLK     APB2时钟为系统时钟 72MHz
        RCC_PCLK2Config(RCC_HCLK_Div1);

        // PCLK1 = HCLK/2     APB1时钟为系统时钟 72MHz/2=36MHz
        RCC_PCLK1Config(RCC_HCLK_Div2);

        // Flash 2 wait state
        FLASH_SetLatency(FLASH_Latency_2);
        // Enable Prefetch Buffer
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

// PLLCLK = 8MHz * 9 = 72 MHz
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

        // Enable PLL
        RCC_PLLCmd(ENABLE);

        // Wait till PLL is ready
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
        {
        }

        // Select PLL as system clock source
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

        // Wait till PLL is used as system clock source
        while(RCC_GetSYSCLKSource() != 0x08)
        {
        }
    }

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO |
                                            RCC_APB2Periph_GPIOA |
                                            RCC_APB2Periph_GPIOB |
                                            RCC_APB2Periph_GPIOC |
RCC_APB2Periph_USART1 |
                                            RCC_APB2Periph_SPI1
                                            , ENABLE);
                                           
 
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG |
                                            RCC_APB1Periph_USART2 |
                                            RCC_APB1Periph_USART3 |
                                            RCC_APB1Periph_TIM3   |
           RCC_APB1Periph_TIM4   |
                                            RCC_APB1Periph_CAN1
//                                            RCC_APB1Periph_CAN2
                                            , ENABLE);
}

/*NVIC配置*/

void NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;

    #ifdef  VECT_TAB_RAM 
    // Set the Vector Table base location at 0x20000000
    NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
    #else  /* VECT_TAB_FLASH  */
    // Set the Vector Table base location at 0x08000000
    NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);  
    #endif

    // Configure one bit for preemption priority
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);


 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

 NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_Init(&NVIC_InitStructure);
   
}

/*管脚初始化*/

void CAN_PinInit(void)
{
 GPIO_InitTypeDef  GPIO_InitStructure;

     /* Configure CAN pin: RX */
 GPIO_InitStructure.GPIO_Pin = PIN_CAN_RX;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
 GPIO_Init(GPIO_CAN, &GPIO_InitStructure);
 
 /* Configure CAN pin: TX */
 GPIO_InitStructure.GPIO_Pin = PIN_CAN_TX;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//GPIO_Mode_Out_PP;
 GPIO_Init(GPIO_CAN, &GPIO_InitStructure);
}

/*CAN1配置函数*/

void CAN_Configuration(void)
{
 CAN_InitTypeDef        CAN_InitStructure;
    CAN_FilterInitTypeDef  CAN_FilterInitStructure;

    // CAN register init
    CAN_DeInit(CAN1);
    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;//ENABLE;报文自动重传
    CAN_InitStructure.CAN_RFLM=DISABLE;//接收溢出时,FIFO未锁定
    CAN_InitStructure.CAN_TXFP=DISABLE;//发送的优先级由标示符的大小决定
    CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;//正常模式下
    //设置can通讯波特率为50Kbps
    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
    CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;
    CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
    CAN_InitStructure.CAN_Prescaler=45;
    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   = (((u32)slave_id<<21)&0xffff0000)>>16;
CAN_FilterInitStructure.CAN_FilterIdLow   = (((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xffff;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh  = 0xFFFF;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow   = 0xFFFF;

    CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;
    CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;   //时能过滤器
    CAN_FilterInit(&CAN_FilterInitStructure);

    CAN_ITConfig(CAN1,CAN_IT_FMP0|CAN_IT_EPV, ENABLE);
}

/*CAN 发送函数*/

unsigned char CAN1_SendData(void)
{
    uint16 i;
 CanTxMsg TxMessage;
    unsigned char TransmitMailbox;

 TxMessage.StdId=0x11;      //标准标识符
 TxMessage.RTR=CAN_RTR_DATA; //数据帧
 TxMessage.IDE=CAN_ID_STD; //标准帧
 TxMessage.DLC=2;       //数据长度 2
 TxMessage.Data[0]=0xCA;     //发送的数据
 TxMessage.Data[1]=0xFE;
 TransmitMailbox=CAN_Transmit(CAN1,&TxMessage); //发送数据
    i = 0xFFF;
 do
{
    _NOP_(5);
 }
    while((CAN_TransmitStatus(CAN1,TransmitMailbox) != CANTXOK) && (--i));

    if(i <= 0x01)
        return 0;
    else
        return 1;
}

/*中断服务函数*/

void USB_LP_CAN1_RX0_IRQHandler(void)
{
 CanRxMsg RxMessage;
 CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);   
}

 三、滤波器配置详细如下:
1、对扩展数据帧进行过滤:(只接收扩展数据帧)
      CAN_FilterInitStructure.CAN_FilterIdHigh   = (((u32)slave_id<<3)&0xFFFF0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLo=(((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh  = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow   = 0xFFFF;
(注:标准帧数据帧、标准远程帧和扩展远程帧均被过滤)
2、对扩展远程帧过滤:(只接收扩展远程帧)
      CAN_FilterInitStructure.CAN_FilterIdHigh   = (((u32)slave_id<<3)&0xFFFF0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow   = (((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_REMOTE)&0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh  = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow   = 0xFFFF;
3、对标准远程帧过滤:(只接收标准远程帧)
      CAN_FilterInitStructure.CAN_FilterIdHigh   = (((u32)slave_id<<21)&0xffff0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow   = (((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_REMOTE)&0xffff;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh  = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow   = 0xFFFF;
4、对标准数据帧过滤:(只接收标准数据帧)
      CAN_FilterInitStructure.CAN_FilterIdHigh   = (((u32)slave_id<<21)&0xffff0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow   = (((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xffff;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh  = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow   = 0xFFFF;
5、对扩展帧进行过滤:(扩展帧不会被过滤掉)
      CAN_FilterInitStructure.CAN_FilterIdHigh   = (((u32)slave_id<<3)&0xFFFF0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow   = (((u32)slave_id<<3)|CAN_ID_EXT)&0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh  = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow   = 0xFFFC;
6、对标准帧进行过滤:(标准帧不会被过滤掉)
      CAN_FilterInitStructure.CAN_FilterIdHigh   = (((u32)slave_id<<21)&0xffff0000)>>16;
      CAN_FilterInitStructure.CAN_FilterIdLow   = (((u32)slave_id<<21)|CAN_ID_STD)&0xffff;
      CAN_FilterInitStructure.CAN_FilterMaskIdHigh  = 0xFFFF;
      CAN_FilterInitStructure.CAN_FilterMaskIdLow   = 0xFFFC;
注:slave_id为要过滤的id号。

其中我们可以开启can错误中断,设置响应的标志位,在大循环里面不断的检测是否错误,一旦错误就重新配置can,这样有效地保证了CAN的正常通信。具体操作代码如下:

 


/*CAN错误中断服务函数*/、

void CAN1_SCE_IRQHandler(void)
{
 CANWorkFlag &= ~CAN_RESET_COMPLETE;
}

/*CAN错误处理函数*/

/************************************************************************
 *函数名称:  CanErrorProcess
 *功能:      CAN故障,错误处理
 *参数说明:  无
 ************************************************************************/
void CanErrorProcess(void)
{
 if ((CANWorkFlag & CAN_RESET_COMPLETE) == 0)
 {
  CAN1_Configuration();
//  CAN2_Configuration();
  CANWorkFlag |= CAN_RESET_COMPLETE;
 }
 
// if((CANWorkFlag & CAN2_RESET_COMPLETE) == 0)
// {
//  CAN1_Configuration();
//  CAN2_Configuration();
//  CANWorkFlag |= CAN2_RESET_COMPLETE;
// }
}

/*错误标志的定义*/

extern uint8 CANWorkFlag;
/************************************************************************
 *  CANWorkFlag 标志位掩码定义
 ************************************************************************/
#define       CAN_INIT_COMPLETE            0x80   //CAN初始化完成标志
//#define       CAN_BUS_ERROR                0x40   //CAN总线错误标志
#define       CAN_RESET_COMPLETE           0x40   //CAN控制器复位完成标志

#define       CAN2_INIT_COMPLETE            0x20   //CAN2初始化完成标志
//#define       CAN_BUS_ERROR                0x40   //CAN总线错误标志
#define       CAN2_RESET_COMPLETE           0x10   //CAN2控制器复位完成标志


以上是我再调试时候添加的,挺有效的;

关键字:STM32  CAN通信  滤波器 引用地址:STM32 CAN通信 滤波器配置总结

上一篇:ARM编译中的RO、RW和ZI DATA区段
下一篇:stm32f105/107互联性时钟配置参考函数

推荐阅读最新更新时间:2024-03-16 15:12

基于STM32的交流永磁同步电机驱动器设计
引言 近年来,随着微电子技术、电力电子技术、现代控制技术、材料技术的迅速发展以及电机制造工艺水平的逐步提高,交流永磁同步电机以其体积小、结构简单等特点在工农业、日常生活以及许多高科技中迅速得到了广泛的应用。因此,研究设计高精度、高性能的永磁同步电机成为现代电伺服驱动系统的一个发展趋势。 伺服驱动器按照功能特征可分为功率板和控制板两个独立的模块,本文在分析交流永磁同步电机控制性能的基础上分别对控制单元和功率驱动单元进行了具体的设计。控制单元作为伺服系统的核心,要求有较高的性能,为此,论文采用意法半导体推出的STM32作为控制核心芯片。它是基于ARM先进架构的Cortex-M3为内核的32位微处理器,主频可高达72 MHz。强大
[单片机]
基于<font color='red'>STM32</font>的交流永磁同步电机驱动器设计
STM32外部中断
68个可屏蔽中断通道,包括EXTI,TIM,ADC,USART,SPI,I²C,RTC等多个外设(F1系列最多的数量,以型号为主); 使用NVIC统一管理中断,每个中断通道都拥有16个可编程优先等级,可以对优先级进行分组,进一步设置抢占优先级和响应优先级。 AFIO内部图 EXTI内部图 中断和事件的区别 NVIC的中断优先级由优先级寄存器的4位(0-15)决定,这四位可以进行切分,分为高N位的抢占优先级, 和4-n位的响应优先级; 抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的话, 按照中断号排队。 操作的是NVIC- IPRx寄存器 中断示例 mai
[单片机]
<font color='red'>STM32</font>外部中断
stm32 直接读写寄存器代码风格总结
简单的总结了一下stm32 寄存器读写代码风格,以备后用: 根据memory mapping 直接写寄存器代码风格: #define GPIOA_BASE1 (uint32_t)0x40010800 #define GPIOA_CRH ((uint32_t*)(GPIOA_BASE1+0x04)) 转换为指针之后,直接读写: *GPIOA_CRH=0x000004B0; //A端口 //复用推挽输出 结构体指针解决连续多个寄存器读写设置: #define Usart1_BASE 0x40013800 typedef struct { __IO uint32_t SR; __IO
[单片机]
<font color='red'>stm32</font> 直接读写寄存器代码风格总结
STM32 的位带操作
位操作就是可以单独的对一个比特位进行读和写,这个在51单片机中非常常见。51单片机中通过关键字sbit来实现位定义,STM32中则是通过访问位带别名区的地址来实现对某一位的操作。 例如51单片机中可以实现以下操作 #define LED_ON 0 sbit LED = P2^0; LED = LED_ON; 而现在STM32的位段、位带别名区就为了实现这样的功能。STM32针对SRM和外设区开辟了两个内存空间(位带区),分别是SRAM和外社区的最低1MB的空间。这两个1MB的内存空间除了可以像正常的 RAM 一样操作外,他们还有自己的位带别名区,位带别名区就是把1MB位带区的每一个位膨胀成一个32位的字,当通过访问位带
[单片机]
<font color='red'>STM32</font> 的位带操作
USB之STM32基础
本篇笔记主要介绍 STM32 相关的知识点,毕竟之后的 CDC 教程是用 STM32 开发的。 为了写这一篇,鱼鹰把 STM32 中文参考手册 USB 相关的从头到尾看了一遍,虽然以前就已经看过了,但这次看,收获又是不同。 不过限于篇幅,鱼鹰不会面面俱到,只介绍和 CDC 相关的一些东西。 要完成 USB 模拟串口(CDC)的实验,STM32 手册是必须细细阅读的,不然代码里面很多操作你是无法看懂的。 其实理解了前面的一些东西,你会发现 STM32 中的 USB 知识和前面的大同小异,毕竟开发芯片的厂家也是按照 USB 标准来实现的,不会差到哪里去。 硬件基础 首先,STM32F103 使用 PA11(USBDM,D-)和 PA1
[单片机]
stm32的USB(二)Fatfs在stm32上的移植
前言 相信大家不会对FAT文件系统感到陌生,在Windows上就能够直接操作FAT文件,Fatfs是一个完全免费和开源的文件系统模块,它支持FATl2、FATl6 和FAT32,支持多个存储媒介,有独立的缓冲区,可以对多个文件进行读/写,在嵌入式系统中得到广泛应用。Fatfs有Fatfs和FatFs/Tiny两个版本,FatFs/Tiny占用RAM较小,但是以更慢的读写速度和更少的API函数为代价,下面以Fatfs版本作介绍大家可以从以下链接下载源码:http://elm-chan.org/fsw/ff/00index_e.html。 移植 Fatfs的层次结构如下图所示: 应用层提供了接口函数,如f_open,f_rea
[单片机]
<font color='red'>stm32</font>的USB(二)Fatfs在<font color='red'>stm32</font>上的移植
总投55亿元,芯投微滤波器项目落户合肥
1月26日,旷达科技集团股份有限公司(以下简称“旷达科技”)发布公告称,公司重要参股公司芯投微电子科技(上海)有限公司(以下简称 “芯投微”)与合肥高新技术产业开发区管委会于当日签订了《芯投微滤波器芯片研发生产总部项目投资合作协议书》。 图源:旷达科技公告 公告资料显示,芯投微设立合肥芯投微电子有限公司作为项目主体公司,在合肥高新区建设滤波器芯片及模组研发、设计及生产总部项目,该项目总投资55亿元人民币,分两期实施。 据公告介绍,此前旷达科技下属公司与建投华科投资股份有限公司联合设立专门的有限合伙企业并投资境内合资公司芯投微,通过芯投微控股滤波器子公司进入射频前端领域。 芯投微将充分利用合肥市突出的区位、人才及科技资源优势投资
[手机便携]
总投55亿元,芯投微<font color='red'>滤波器</font>项目落户合肥
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
热门活动
换一批
更多
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多精选电路图
换一换 更多 相关热搜器件
更多每日新闻
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved