DAY11-CAN总线和ADC

201 阅读4分钟
title: DAY11-CAN总线和ADC
categories: STM32
abbrlink: 221cbc9c
date: 2022-07-28 23:46:42

(3)控制段

0

r0,r1为保留位,默认是显性电平 DLC由4位组成,表示数据段的长度(0~8)

(4)数据段

长度0~8字节,高位先出

0

(5)CRC段

CRC错误校验,由15位CRC校验码和1位界定符组成,校验出错反馈错误信息,利用错误帧请求重发,重发次数可以通过软件设置。

0

(6)ACK段

由一位ACK槽和一位ACK界定符组成,发送方的ACK槽是隐性电平,接收方确认收到正确的数据后以显性电平作为应答。

0

(7)帧结束

7位隐性电平

0

4.CAN的位时序

0

CAN传输1位由4段组成:同步段,传播段,相位缓冲段1,相位缓冲段2。1位结束后会使用再同步补偿宽度(SJW)进行再补偿,这样设计的原因是让发送方和接收方的时序保持统一(没有时钟线)

0

(1)同步段(SS)

同步段用于实现时序的调整,完成显性电平/隐性电平的转换,也就是准备该位要发送的电平

(2)传播时间段(PTS)

用于吸收网络上的物理延迟,物理延迟包括发送的延迟,接收的延迟和信号传播的延迟。

(3)相位缓冲段(PBS)

对于电平转换未被包含的部分进行补偿,同时和SJW一起补偿各单位的时钟误差,读取电平在该段完成。

(4)再同步补偿宽度(SJW)

补偿前面同步的误差

注意:接收方的采样一定在PBS1和PBS2之间,由于PTS误差的变动,PBS的补偿也会随着误差的变化而变化,实现1位传输时间的固定,SJW对PBS的补偿进行二次补偿。

0

1位时间 = 8~25Tq
SS = 1Tq
PTS = 1~8Tq
PBS = 2~8Tq
SJW = 1~4Tq

5.stm32f4的CAN控制器

stm32芯片带有bxCAN控制器,支持CAN协议的2.0A和2.0B,最快速度支持1Mbps,能够自动发送CAN报文,支持标准帧和扩展数据帧,控制器带有三个发送邮箱存储报文,还有两个FIFO,支持ID过滤,可配置自动重发。

(1)工作模式

初始化模式:初始化CAN控制器

正常模式:正常发送和接收数据

睡眠模式:低功耗

(2)测试模式

静默模式:停止对外发送报文

环回模式:报文不发送到总线,直接发给自己

环回和静默组合模式

调试模式

(3)通信速率

波特率 = 42M/分频系数/(tbs1+tbs2+sjw)

(4)接收中断

FMPx表示收到消息

6.原理图

0

连接到了CPU的PD0 PD1,具有CAN的复用功能

7.CAN总线通信的库函数实现

添加CAN总线通信的库函数源码

0

(1)开启GPIOD和CAN1的时钟

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

(2)配置GPIO为CAN复用功能

GPIO_Init(...);
GPIO_PinAFConfig(...);

(3)初始化CAN1

uint8_t CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct);
参数:
    CANx - 哪路CAN
    CAN_InitStruct - CAN初始化结构
    
typedef struct
{
  uint16_t CAN_Prescaler;   /*!< 总线时钟的分频系数 1 to 1024. */
  
  uint8_t CAN_Mode;         /*!< 工作模式 @ref CAN_operating_mode */
​
  uint8_t CAN_SJW;          /*!< SJW极限值 @ref CAN_synchronisation_jump_width */
​
  uint8_t CAN_BS1;          /*!< 相位缓冲段1长度 @ref CAN_time_quantum_in_bit_segment_1 */
​
  uint8_t CAN_BS2;          /*!< 相位缓冲段2长度 @ref CAN_time_quantum_in_bit_segment_2 */
  
  FunctionalState CAN_TTCM; /*!< 时间触发使能 ENABLE or DISABLE. */
  
  FunctionalState CAN_ABOM;  /*!< 自动离线使能 ENABLE or DISABLE. */
​
  FunctionalState CAN_AWUM;  /*!< 自动唤醒使能 ENABLE or DISABLE. */
​
  FunctionalState CAN_NART;  /*!< 自动重发使能 ENABLE or DISABLE. */
​
  FunctionalState CAN_RFLM;  /*!< 接收FIFO锁定使能 ENABLE or DISABLE. */
​
  FunctionalState CAN_TXFP;  /*!< 发送FIFO优先级使能 ENABLE or DISABLE. */
} CAN_InitTypeDef;    

(3)初始化过滤器

void CAN_FilterInit(CAN_FilterInitTypeDef* CAN_FilterInitStruct);
//参数就是过滤器初始化结构typedef struct
{
  uint16_t CAN_FilterIdHigh;         /*!< 过滤器ID寄存器的高16位 0x0000 and 0xFFFF */
​
  uint16_t CAN_FilterIdLow;          /*!< 过滤器ID寄存器的低16位 0x0000 and 0xFFFF */
​
  uint16_t CAN_FilterMaskIdHigh;     /*!< 过滤器屏蔽寄存器的高16位 0x0000 and 0xFFFF */
​
  uint16_t CAN_FilterMaskIdLow;      /*!< 过滤器屏蔽寄存器的低16位 0x0000 and 0xFFFF */
​
  uint16_t CAN_FilterFIFOAssignment; /*!< 接收FIFO的选择 @ref CAN_filter_FIFO */
  
  uint8_t CAN_FilterNumber;          /*!< 过滤器编号 0 to 13. */
​
  uint8_t CAN_FilterMode;            /*!< 过滤器模式 @ref CAN_filter_mode */
​
  uint8_t CAN_FilterScale;           /*!< 过滤器长度 @ref CAN_filter_scale */
​
  FunctionalState CAN_FilterActivation; /*!< 过滤器使能 ENABLE or DISABLE. */
} CAN_FilterInitTypeDef;

(5)配置发送/接收的结构体

//发送数据结构体
typedef struct
{
  uint32_t StdId;  /*!< 标准帧ID 0 to 0x7FF. */uint32_t ExtId;  /*!< 扩展帧ID 0 to 0x1FFFFFFF. */uint8_t IDE;     /*!< IDE标志 标准帧/扩展帧 @ref CAN_identifier_type */uint8_t RTR;     /*!< RTR标志 数据帧/遥控帧 @ref CAN_remote_transmission_request */uint8_t DLC;     /*!< 数据段长度 0 to 8 */uint8_t Data[8]; /*!< 数据内容 0 to 0xFF. */
} CanTxMsg;
​
//接收数据结构体
typedef struct
{
  uint32_t StdId;  /*!< 标准帧ID 0 to 0x7FF. */uint32_t ExtId;  /*!< 扩展帧ID 0 to 0x1FFFFFFF. */uint8_t IDE;     /*!< IDE标志 标准帧/扩展帧 @ref CAN_identifier_type */uint8_t RTR;     /*!< RTR标志 数据帧/遥控帧 @ref CAN_remote_transmission_request */uint8_t DLC;     /*!< 数据段长度 0 to 8 */uint8_t Data[8]; /*!< 数据内容 0 to 0xFF. */uint8_t FMI;     /*!< 过滤器放入的内容 0 to 0xFF */
} CanRxMsg;

(6)初始化CAN的接收中断

NVIC_Init(...);
CAN_ITConfig(...);

(7)发送和接收数据的接口

接收:
    void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage);
​
发送:
    uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage);
    uint8_t CAN_TransmitStatus(CAN_TypeDef* CANx, uint8_t TransmitMailbox);

8.上位机使用

打开上位机软件

0

(1)串口设置

0

打开后会读到当前模块的设置

0

(2)将CAN模块设置为环回模式,波特率500Kbps

0

(3)测试模块的发送和接收

0

9.模块和开发板的连接

0

练习:

将两块开发板的CAN接口连接,测试互相发送和接收

如果没有两块开发板使用环回模式自己发给自己

10.CAN的过滤器设置

stm32的CAN过滤器有两种模式:列表模式和掩码模式

(1)列表模式

列表模式表示只接收符合给定ID的帧,一共有2个32位的寄存器,分为16位模式和32位模式。

16位列表模式一个ID占16位,一共可以给4个ID,通常用于标准帧,标准帧的ID放入16位中的高11位。扩展帧只能存ID的15~17于低三位,另外两位存IDE位和RTR位,分别表示扩展帧(1)/标准帧(0),数据帧(0)/遥控帧(1)。

0

32位列表模式一个ID占32位,一共可以给2个ID,通常用于扩展帧,扩展帧的ID是29位,放入寄存器的高29位,低位放IDE,RTR和0

0

(2)掩码模式

掩码模式只接收符合掩码要求的帧,一共有2个32位的寄存器,分为16位模式和32位模式。

第一个寄存器给ID的值,第二个寄存器对一个寄存器进行掩码操作,只有第一个寄存器中对应第二个寄存器中为1的位才需要匹配。

0

三十.ADC

1.概念

ADC,指的是Analog-to-Digtal Converter(模数转换)。我们把连续变化的信号叫模拟信号,离散的非连续的信号叫数字信号,现实生活中所有的信号属于模拟信号,比如声音,电压,压强,温度.......,但是计算机只能存储和处理数字信号。ADC实现的就是这种将模拟信号转换成数字信号的功能,DAC将数字信号转换成模拟信号。

2.ADC的转换过程

采样 ======> 量化 =====> 编码

3.ADC类型

ADC有积分型和逐次逼近型的区分,积分型电路简单,成本低,但是转换事件比较长。逐次逼近型成本相对高,转换速度相对快。

4.stm32f4的内部ADC

0

0

注:P10跳线为ADC提供参考正电压,必须连上ADC才能工作,测量范围:0 ~ 3.3V

0

ADC测量电路:

0

滑动变阻器的分压引脚连接到了PA5,PA5具有ADC12的通道5的复用功能

5.ADC的库函数编程实现

添加ADC的库函数源码到工程中

0

(1)开启GPIOA和ADC1时钟

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

(2)将GPIO配置为模拟功能

GPIO_Init

(3)复位ADC

ADC_DeInit(...);

(4)初始化ADC的分频系数(配置CCR寄存器,通用配置)

void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct);
//参数就是初始化结构体typedef struct 
{
  uint32_t ADC_Mode;                      /*!< 模式选择 多重/独立 @ref ADC_Common_mode */                                              
  uint32_t ADC_Prescaler;                 /*!< 分频系数 4分频 @ref ADC_Prescaler */
  uint32_t ADC_DMAAccessMode;             /*!< DMA模式选择 @ref ADC_Direct_memory_access_mode_for_multi_mode */
  uint32_t ADC_TwoSamplingDelay;          /*!< 2次采样时间间隔 5时钟周期 @ref ADC_delay_between_2_sampling_phases */
}ADC_CommonInitTypeDef; 

(5)初始化ADC1,设置工作模式,规则序列(专用配置)

void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
参数:
    ADCx - 哪个ADC
    ADC_InitStruct - ADC初始化结构
    
typedef struct
{
  uint32_t ADC_Resolution;                /*!< 分辨率 12位 @ref ADC_resolution */                                   
  FunctionalState ADC_ScanConvMode;       /*!< 扫描使能 DISABLE */ 
  FunctionalState ADC_ContinuousConvMode; /*!< 连续转换使能 DISABLE. */
  uint32_t ADC_ExternalTrigConvEdge;      /*!< 外部触发信号选择 @ref ADC_external_trigger_edge_for_regular_channels_conversion */
  uint32_t ADC_ExternalTrigConv;          /*!< 外部触发选择 @ref ADC_extrenal_trigger_sources_for_regular_channels_conversion */
  uint32_t ADC_DataAlign;                 /*!< 数据对齐选择 @ref ADC_data_align */
  uint8_t  ADC_NbrOfConversion;           /*!< 规则序列长度 1 */
}ADC_InitTypeDef;    

(6)使能ADC

ADC_Cmd(...);

(7)配置通道参数(转换ADC哪个通道,采样周期)

void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
参数:
    ADCx - 哪个ADC
    ADC_Channel - 哪个通道
    Rank - 规则组的编号
    ADC_SampleTime - 采样周期

(8)使用软件操作启动转换

void ADC_SoftwareStartConv(ADC_TypeDef* ADCx);

(9)等待转换完成

while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)!=SET);

(10)获取转换结果

uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);

6.光敏电阻

光敏电阻的阻值会随着光照强度的变化而变化

0

0

作业:

1.通过CAN命令控制LED的亮灭