软件设计报告

目录

1 时序板软件设计... 3

2 时序板软件模块设计... 3

2.1 数据接收发送模块详细设计... 3

2.1.1 I2C模块初始化... 3

2.1.2 I2C发送数据(单片机是I2C通信的主机) 4

2.1.3 I2C接收数据信息(单片机是I2C通信丛机模式) 6

2.2 电压采集详细设计... 8

2.2.1 ADC模块初始化... 8

2.2.2 ADC数据处理... 10

2.3 温度采集详细设计... 10

2.2.1 温度传感器驱动... 10

2.2.2 各寄存器描述... 11

2.2.3 温度处理... 12

3 函数主程序介绍... 12

3.1 初始化介绍... 12

3.1.1 变量初始定义... 12

3.1.2 模块配置... 12

3.2 主程序介绍... 13

3.2.1 数据接收... 13

3.2.2 数据分析处理... 13

3.2.3 数据发送... 14

3.3 软件流程... 15

1 时序板软件设计

时序板软件部分的主控芯片采用的是STM32F103C8T6单片机,主要完成的功能是接收来自时序版逻辑模块的指令信息,对自身的电压和温度进行检测以及将结果发送出去。数据的接收和发送采用的是I2C总线。下图所示是时序版软件部分的结构图。

2 时序板软件模块设计

本软件涉及到的数据接收发送和数据采集。数据采集包括电压采集和温度采集。主要涉及到STM32F103C8T6单片机的I2C模块,ADC模块,GPIO模块。

2.1 数据接收发送模块详细设计

数据接收发送的I2C接口主要用于接收来自BMC主控板的指令信息,同时将自身采集到的温度和电压信息通过此接口返回到BMC主控板。

STM32F103C8T6单片机共有两个I2C模块,分别是STM32F103C8T6单片机硬件的43引脚(I2C1_SDA)、42引脚(I2C1_SCL)、22引脚(I2C2_SDA)、21引脚(I2C2_SCL),本设计中只用到了I2C1,I2C2的引脚直接拉低接地。

2.1.1 I2C模块初始化

软件中具体指的是I2C_Configuration()子函数中的内容,下面将对这个函数进行详细的介绍。

①I2C复位使能

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1|RCC_APB1Periph_I2C2,ENABLE)使能I2C模块

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO , ENABLE)使能复用引脚

②配置SDA和SCL总线

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_10|GPIO_Pin_11配置I2C1的SCL为GPIO的PB6,SDA为GPIO的PB 7,配置I2C2的SCL为GPIO的PB10,SDA为GPIO的PB11

②配置I2C基本信息

I2C的时钟速率为100000Hz,I2C_InitStructure.I2C_ClockSpeed = 100000

使能I2C应答模式,I2C_InitStructure.I2C_Ack = I2C_Ack_Enable

使能I2C应答,   I2C_AcknowledgeConfig(I2Cx, ENABLE);

2.1.2 I2C发送数据(单片机是I2C通信的主机)

void Drv_I2C_Write(I2C_TypeDef *I2Cx,u8 I2C_Addr,u8 *buf,uint16_t num)

函数描述:I2C发送数据

函数功能:将采集到的自身传感器信息发送回BMC主控板

函数参数:I2Cx----I2C通道选择,可选择1或者2

          I2C_Addr-------发送数据信息的目标地址

          buf------发送的数据信息

          num-----发送数据的字节数

实现过程:

①产生I2C通信启动信号

void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState)

函数描述:启动一个I2C通道

函数参数:I2Cx----I2C通道选择,可选择1或者2

NewState-----I2C通道状态,可选择ENABLE或者DISENABLE

  ②启动信号完成确认

ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)

  函数描述:确认总线是否空闲

  函数参数:I2Cx----I2C通道选择,可选择1或者2

                I2C_EVENT---I2C目前状态事件,可选择BUSY、MSL、ADDR等状态

   注意:此函数必须在I2C_GenerateSTART之后使用,用于保证此时I2C总线处于闲的状态,CPU可以控制I2C进行后面的操作。

③写目标地址

void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction)

函数描述:发送字节地址用于选择发送数据信息的从设备

函数参数:I2Cx----I2C通道选择,可选择1或者2

                        Address---发送数据的目标地址

                        I2C_Direction---I2C的方向,可选择接受或者发送

④目标地址完成确认

具体参考步骤②

注意:此函数必须在写完目标地址后使用,用于确保写完成。

⑤发送数据信息

void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data)

函数描述:用于发送数据

函数参数:I2Cx----I2C通道选择,可选择1或者2

                        Data---发送的数据

⑥发送完成确认

具体参考步骤②

注意:此函数必须在发送数据完成后,用于确保数据已经完全发送完成。

⑦产生I2C通信停止信号

void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState)

函数描述:停止一个I2C通道

函数参数:I2Cx----I2C通道选择,可选择1或者2

NewState-----I2C通道状态,可选择ENABLE或者DISENABLE

2.1.3 I2C接收数据信息(单片机是I2C通信丛机模式)

需要注意的是I2C作为丛机模式时,其读数据的位置都是确定的,因此在读取数据时需要对I2C总线的状态分别进行多次判断。

uint16_t Drv_I2C_Read(I2C_TypeDef *I2Cx,u8 *buf,uint16_t num)

函数描述:I2C接收数据

函数功能:从BMC主控板接收指令信息

函数参数:I2Cx----I2C通道选择,可选择1或者2

buf-----接收数据缓存区

num-------接收到的数据字节数

实现过程:

①接收启动信号

while(!I2C_CheckEvent(I2Cx,I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED))

注意:I2C_CheckEvent函数的主要功能详见I2C发送数据的步骤②。在I2C接收数据过程中,此步骤相当于一个接收启动信号,意味着单片机在I2C总线的主机地址后又检测到一个启动信号

②检测接收标志

while(!I2C_CheckEvent(I2Cx,I2C_EVENT_SLAVE_BYTE_RECEIVED_DBG));

注意:I2C_CheckEvent函数的主要功能详见I2C发送数据的步骤②。I2C接收数据过程中,当完成了第一步接收启动后需要对接收标志进行判断,为确保准确的接收数据。

③接收数据并存储

*buf= I2C_ReceiveData(I2Cx); 

语句描述:接收数据并且存储

语句功能:通过I2C总线接收数据信息,并且将其保存在数据缓存区buf中。

语句参数:I2Cx----I2C通道选择,可选择1或者2

buf-----接收数据缓存区

④接收停止信号

while(!I2C_CheckEvent(I2Cx,I2C_EVENT_SLAVE_STOP_DETECTED));  

注意:I2C_CheckEvent函数的主要功能详见I2C发送数据的步骤②。

⑤清空接收标志

I2C_ClearFlag(I2Cx, I2C_FLAG_STOPF);

函数描述:清楚接收标志

函数参数:I2Cx----I2C通道选择,可选择1或者2

              I2C_FLAG_STOPF------清楚标志

2.2 电压采集详细设计

本软件中电压采集主要使用的是STM32F103C8T6单片机自带的ADC模块,共采集单片机板上的六路电压值,即EVM_1V0、EVM_1V8、EVM_2V5、EVM_3V3、EVM_5V0、3V3_AUX,硬件上分别连接的是STM32F103C8T6单片机的17、15、16、14、10和11引脚。

STM32F103C8T6单片机的DMA通道支持ADC外设的使用,本软件中采用DMA的方式直接将ADC转换的结果通过DMA读出存储于缓存区中。本软件采用单片机自带的ADC模块,因此数据采集为12位的。

下面将介绍ADC模块的工作流程

2.2.1 ADC模块初始化

本软件中ADC模块中使用了DMA,进行初始化时不仅需要初始化ADC的基本功能,同时还需要对DMA进行配置。ADC_Voltage_Configuration()配置项有以下几种:

①使能ADC和DMA模块

 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA| RCC_APB2Periph_AFIO, ENABLE);

②配置GPIO的方向

对自身的电压值进行采集时,硬件接口上直接连接的是IO引脚,因此需要对IO引脚的方向进行控制。将引脚设置为输入模式,用于ADC的采集。

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

 GPIO_Init(GPIOA, &GPIO_InitStructure);

③DMA的配置

设置DMA的原地址为ADC1地址 ,即 DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;

DMA的目标地址为  ADC_ConvertedValue ,即DMA_InitStructure.DMA_MemoryBaseAddr=(u32)&ADC_ConvertedValue;

DMA数据缓冲区大小为6个字节,即  DMA_InitStructure.DMA_BufferSize = 6;

④ADC配置

选择ADC为独立工作模式,即  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;

使能6个ADC通道,即  ADC_InitStructure.ADC_NbrOfChannel = 6;

每个ADC通道的采样时间和对应传感器位置设置,即  ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);其中ADC的采样周期为ADC_SampleTime_239Cycles5,ADC通道0对应1号电压传感器,依次类推。

⑤启动ADC采集

首先需要将ADC和DMA通道使能,即  ADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE);

然后复位ADC采集寄存器并且等待复位完成,即  ADC_ResetCalibration(ADC1);while(ADC_GetResetCalibrationStatus(ADC1));

接下来使能ADC采集等待采集完成,即  ADC_StartCalibration(ADC1);while(ADC_GetCalibrationStatus(ADC1));

最后,启动ADC转换过程,即ADC_SoftwareStartConvCmd(ADC1, ENABLE);

2.2.2 ADC数据处理

2.2.1中ADC模块的初始化启动了ADC转换模块,STM32F103C8T6单片机会自动在内部进行转换数据存储于ADC_ConvertedValue[6]数组中。数据处理转换时只需要调用函数下面函数即可。

void  drv_ipmc_get_voltage_sensor(void)

函数描述:ADC数据处理

函数功能:将单片机转换的ADC数字量转换为实际的电压值并且存储于电压缓冲区voltage_sensor_value[6]。

数据处理:ADC为12位的,参考电压为3.3V,根据数模转换公式可获得真实的电压值。如程序中所使用的转换方式:voltage_sensor_value[uiLoop]=(voltage_sensor_value[uiLoop]/4096)*3.3;

2.3 温度采集详细设计

板中有一个单线温度传感器TMP141,通过它来实时监测单板工作温度环境,并将其结果发送出去。STM32f103的PA8连接TMP141的SWD管脚。通过PA8来模拟TMP141的读写时序。下面介绍温度采集子函数:

float drv_ipmc_get_temp_sensor(void)

函数描述:读取温度传感器值

函数功能:读取TMP141的温度传感器的值,并且将其进行处理

返回值:温度转换的数字量

2.2.1 温度传感器驱动

TMP141为单线温度传感器,需要通过GPIO模拟芯片时序来实现对温度的读取。TMP141驱动过程如下图所示:

2.2.2 各寄存器描述

a)       Device Control寄存器

由硬件连接得到TMP141的设备地址是0x03写Device Control寄存器,地址0x05,设置该寄存器的Bit4,Enable Function1(ENAB)为1,即可使能温度测量。使用的函数为:

void write_byte(u16 device_NO,u16 reg_NO,u16 data)

函数描述:向某一寄存器写值

函数功能:使能TMP141的设备控制寄存器,启动开始工作。

函数参数:device_NO-------设备地址0x03

              reg_NO-----TMP141的设备控制寄存器0x05

              data-----要写入控制寄存器的值,可选ENABLE或者DISENABLE。

b)      Temperature Conrol寄存器

写Temperature  Control寄存器,地址为0x0A,设置该寄存器的Bit1,Enable Sensor(EN_S)为1,开始温度测量。使用的函数与设备控制寄存器中相同。

c)       Temperature Readout寄存器

读Temperature Readout寄存器,地址0x09,通过读取该寄存器即可获取温度值。使用的函数如下:

u16 read_byte(u16 device_NO,u16 reg_NO)

函数描述:读取某一个设备寄存器中的值

函数功能:用于从TMP141的温度读取寄存器中读取温度传感器转换的值。

函数参数:device_NO-------设备地址0x03

              reg_NO-----TMP141的设备控制寄存器0x09

函数返回:返回16位的温度数字量

2.2.3 温度处理

TMP141温度传感器进行转换后会得到的是温度对应的数字信息,根据其TMP141的手册表将数字信息进行转换得到其准确的温度数据。

3 函数主程序介绍

本软件中函数的主程序实现的是一个数据接收,采集和发送的大的循环过程。接下来将按照主程序的运行过程介绍每一个循环过程。

3.1 初始化介绍

初始化中包括对变量的初始定义,模块配置,缓冲区清缓存等。

3.1.1 变量初始定义

stIPMC_Message ipmc_sensor_message;对结构体的数据进行初始化,此结构体里边存储的发送数据的完整一包科学数据。

    u32 sensor_value = 0;u8 I2C2_Buffer_Rx[8] = {0};float current_sensor_value=0;float tmp141_sensor_value = 0;此四个语句是对软件中使用的变量进行清零操作。

3.1.2 模块配置

本软件中使用了GPIO,I2C和ADC模块,因此在主函数中需要分别对此模块进行初始设置。ADC_Voltage_Configuration()指ADC配置,详见2.2.1中的ADC模块初始化,I2C_Configuration()详见2.1.1中的初始化配置。Onewire_Enable_GPIO_Port();指的是使能GPIO引脚,主要使用的函数是RCC_APB2PeriphClockCmd,下面是对此函数额的说明。

说明:使能高速APB2接口时钟

原型:voidRCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)

函数参数:

3.2 主程序介绍

3.2.1 数据接收

单片机上电进行初始化之后等待接收来自BMC主控板的指令信息Drv_I2C_Read(I2C1, I2C2_Buffer_Rx,sizeof(I2C2_Buffer_Rx))。通过I2C1总线接口,将接收到的数据缓存在I2C2_Buffer_Rx中,共8个字节。

3.2.2 数据分析处理

首先需要分析I2C2_Buffer_Rx缓冲区每一个字节的含义,若if( I2C2_Buffer_Rx[1]== 1 )表示主控板发来的指令信息是确认此时单片机板是否正常工作,若指令正确则将设备头,单片机板地址等保存在结构体返ipmc_sensor_message存储空间内,然后将此结构体中保存的数据返回给BMC主控板。返回的值主要有以下几个:         ipmc_sensor_message.ucRev = 0xAA;设备的代码

ipmc_sensor_message.MessageType = I2C2_Buffer_Rx[1];接收到的指令信息

ipmc_sensor_message.SlotAddr = board_own_addr;单片机板的地址0x1C

ipmc_sensor_message.SlotNum = I2C2_Buffer_Rx[2];单片机板槽的标号

若if( I2C2_Buffer_Rx[1]== 2 )表示此时主控板发来的指令信息是传感器的命令,单片机开始进行数据采集。首先需要将一些固定的值存储在结构体ipmc_sensor_message存储空间内,存储方式与3.2.2中相同,其次需要对I2C2_Buffer_Rx[4]信息进行判断。假若if(I2C2_Buffer_Rx[4] == voltage_sensor)表示此时主控板需要的是单片机板六个电压值;假若if(I2C2_Buffer_Rx[4] == temp_sensor)表示此时主控板需要得到单片机板的温度值,然后在进行处理。

1、          if(I2C2_Buffer_Rx[4] == voltage_sensor)

数据分析得到此命令时表示电压采集,此时直接调用drv_ipmc_get_voltage_sensor()函数即可,获得的六个电压值存储在voltage_sensor_value[6]缓冲区中,接下来通过I2C2_Buffer_Rx[5]判断 的是哪个电压值,然后根据对应关系将其存储在ipmc_sensor_message.SensorValue[2]中。

2、          if(I2C2_Buffer_Rx[4] == temp_sensor)

数据分析得到此命令时表示需要进行温度采集,调用函数drv_ipmc_get_temp_sensor()即可获得温度值,然后将其存储在ipmc_sensor_message.SensorValue[2]存储空间中。

3.2.3 数据发送

数据发送时直接调用函数Drv_I2C_Write(I2C1,board_one_addr<<1,(u8*)&ipmc_sensor_message,sizeof(ipmc_sensor_message)),此函数的具体描述详见2.1中即可,数据发送的格式如下表所示。

3.3 软件流程

主程序流程如下图所示。

相关推荐