STM32F103VCT6在uCOS-II下使用SPI1,中断接收方式。现在现象是在SPI_BaudRatePrescaler 设置为SPI_BaudRatePrescaler_4时程序可以正常运行,减慢SPI总线速率则程序无法运行。异常情况下仿真程序可以运行,但运行速度明显异常。
附上SPI相关初始化及应用程序片段,望大师能帮小弟查出问题,万分感谢。
/**
******************************************************************************
* @file BSP_LTC2315.c
* @author
* @version V1.0
* @date 2016-12-13
* @brief LTC2315驱动程序,完成相关GPIO初始化及SPI模块初始化。
******************************************************************************
* @attention
*
* 实验平台:3D_Ceiling_E3
* 硬件资源:
* MCU: STM32F103VCT6/LQFP100
* OSC: 8.00MHz
* 设备号 --> 短路帽 --> 引脚号(使能电平)
* CONV N.C PA04-Pin29(H)
* SCK N.C PA05-Pin30(X)-SPI1_SCK
* SDO N.C PA06-Pin31(X)-SPI1_MISO
*
******************************************************************************
**/
#include "includes.h"
extern OS_EVENT *SPI1_RXNE_sv; /* SPI1_RXNE 中断接收完毕信息量声明 */
/**
******************************************************************************
* @name SPI1_Configuration
* @param Null
* @retval Null
* @author ZERO
* @version V1.0
* @date 2015-03-11
* @brief SPI1参数配置
******************************************************************************
**/
static void SPI1_Configuration(void)
{
// 申请初始化结构体
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// Enable SPI1 and GPIO clocks
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// SPI_FLASH_SPI Periph clock enable
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
// Configure SPI_FLASH_SPI pins: NSS
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Configure SPI_FLASH_SPI pins: SCK
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Configure SPI_FLASH_SPI pins: MISO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* SPI1 configuration */
SPI_Cmd(SPI1, DISABLE); // 禁用SPI1
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // SPI模式 -> 四线制全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // 主机模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; // 数据帧 -> 16Bit
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // 时钟极性 -> H
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // 时钟相位 -> 偶数边采样(上升沿)
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // NSS由内部管脚管理
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; // FPCLK分频系数(SPI 18M@sys 72M),LTC2312_fsck_MAX:20MHz
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 高位数据居前
SPI_InitStructure.SPI_CRCPolynomial = 7; // CRC参数(多项式)
SPI_Init(SPI1, &SPI_InitStructure);
/* SPI1 NVIC configuration */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE); // 开启SPI1接收中断
///* Enable SPI1 */
//SPI_Cmd(SPI1, ENABLE);
}
/**
******************************************************************************
* @name SPI_Transfer_Word
* @param u16 tx, u16 *rx
* @retval Null
* @author ZERO
* @version V1.0
* @date 2015-03-11
* @brief SPI1读取1个word
******************************************************************************
**/
static void SPI_Transfer_Word(u16 tx, u16 *rx)
{
INT8U err;
union
{
u8 b[2];
u16 w;
} data_tx; // 8Bit处理器兼容设置
union
{
u8 b[2];
u16 w;
} data_rx; // 8Bit处理器兼容设置
data_tx.w = tx;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI1_CS_ON; //! 1) Pull CS low
#if 0 // 数据帧 -> 8Bit
SPI_I2S_SendData(SPI1, data_tx.b[1]);
OSSemPend(SPI1_RXNE_sv, 0, &err); // 等待SPI1接收成功信号
data_rx.b[1] = SPI_I2S_ReceiveData(SPI1); //! 2) Read MSB and send MSB
SPI_I2S_SendData(SPI1, data_tx.b[0]);
OSSemPend(SPI1_RXNE_sv, 0, &err); // 等待SPI1接收成功信号
data_rx.b[0] = SPI_I2S_ReceiveData(SPI1); //! 3) Read LSB and send LSB
#else // 数据帧 -> 16Bit
SPI_I2S_SendData(SPI1, data_tx.w);
OSSemPend(SPI1_RXNE_sv, 0, &err); // 等待SPI1接收成功信号
data_rx.w = SPI_I2S_ReceiveData(SPI1); // 读取SPI1接收缓存器
#endif
*rx = data_rx.w;
SPI1_CS_OFF; //! 4) Pull CS high
}
/**
******************************************************************************
* @name SPI1_init
* @param N.C.
* @retval Null
* @author ZERO
* @version V1.0
* @date 2016-12-22
* @brief SPI1初始化函数
******************************************************************************
**/
void SPI1_init(void)
{
SPI1_Configuration();
}
/**
******************************************************************************
* @name SPI1_connect
* @param N.C.
* @retval Null
* @author ZERO
* @version V1.0
* @date 2016-12-22
* @brief SPI1使能函数
******************************************************************************
**/
void SPI1_connect(void)
{
SPI1_CS_OFF; //! 1) Pull Chip Select High
SPI_Cmd(SPI1, ENABLE); //! 使能SPI
}
/**
******************************************************************************
* @name LTC2315_read
* @param uint16_t *adc_code
* @retval returns 16-bit data
* @author ZERO
* @version V1.0
* @date 2015-03-11
* @brief Reads the ADC and returns 16-bit data
******************************************************************************
**/
void LTC2315_read(uint16_t *adc_code)
{
uint16_t dummy_command = 0;
SPI_Transfer_Word(dummy_command, adc_code);
}
/**
******************************************************************************
* @name Data_code_to_avg
* @param uint16_t adc_code, uint8_t shift, float vref
* @retval 缓存区平均值计算
* @author ZERO
* @version V1.0
* @date 2017-02-11
* @brief
* 采样值 C、累加器 S,平均值 A,采样次数 N
* 初始化:A=初始值,S=A*N
* S = S - A + C(i) i从第二个起,不算A
* A = S / N
* 只要 S 的量程足够,N可以任意调整。
* C = ADC读取值
* S = ADC累加器
* A = ADC平均值
* N = 样本容量
******************************************************************************
**/
uint16_t Data_code_to_avg(uint16_t C,uint16_t A,uint8_t N,uint32_t *S)
{
*S = *S - A + C;
return (uint16_t)(*S / N);
}
/**
******************************************************************************
* @name LTC2315_code_to_voltage
* @param uint16_t adc_code, uint8_t shift, float vref
* @retval 电压值转换
* @author ZERO
* @version V1.0
* @date 2015-03-11
* @brief Calculates the voltage corresponding to an adc code in offset binary, given the reference voltage (in volts)
******************************************************************************
**/
float LTC2315_code_to_voltage(uint16_t adc_code, uint8_t shift, float vref)
{
float voltage;
adc_code = adc_code << shift; //!1)the data is left justified to bit_14 of a 16 bit word
voltage = (float)adc_code;
voltage = voltage / (pow(2, 16) - 1); //! 2) This calculates the input as a fraction of the reference voltage (dimensionless)
voltage = voltage * vref; //! 3) Multiply fraction by Vref to get the actual voltage at the input (in volts)
return(voltage);
}
/**
******************************************************************************
* @name SPI_ISR
* @param SPI_TypeDef* SPIx
* @retval SPI中断服务函数
* @author ZERO
* @version V1.0
* @date 2017-02-06
* @brief
******************************************************************************
**/
void SPI_ISR(SPI_TypeDef* SPIx)
{
INT8U err = 0;
if (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == SET) // 接收标志位判断
{
SPI_I2S_ClearITPendingBit(SPIx, SPI_I2S_IT_RXNE); // 清除相关标志位
if (SPIx == SPI1)
{
err = OSSemPost(SPI1_RXNE_sv); // 发出SPI1信号量
}
}
}
/*
*********************************************************************************************************
* (c) Copyright 1992-2014, Shonjet
* All Rights Reserved
*
* File : app_ltc2315.c
* By : ZERO
* Effect : LTC2315 APP
* Version : V1.00 09.2014
* For : ARMv7M Cortex-M3
* System : uCOS-II 2.86
* API : STM32F10x_StdPeriph_Lib_V3.5.0
* Toolchain : MDK-ARM Standard Version: 4.72.0.0
* Velease Note:
* ---------------
* 1. 创建文件V1.00. 22.12.2016
*
* LICENSING TERMS:
* ---------------
*
*********************************************************************************************************
*/
#include "includes.h"
static uint8_t ADC_SampleSize = 30; // 设置采样样本容量
static uint8_t LTC2315_bits = 14; //!< Default set for 14 bits
static uint8_t LTC2315_shift = 1;
void Task_ADC_LTC2315(void *p_arg)
{
uint16_t adc_code; // The LTC2315 code
uint16_t adc_avg;
uint32_t adc_acc;
float adc_voltage; // The LTC2315 voltage
(void)p_arg; /* 'p_arg' 并没有用到,防止编译器提示警告 */
/*-------------------任务主体------------------*/
// SPI1初始化工作
SPI1_init();
SPI1_connect();
LTC2315_read( &adc_code); // discard the first reading
OSTimeDlyHMSM(0, 0, 0, 100);
LTC2315_read( &adc_code);
adc_code >>= 16 - LTC2315_bits;
adc_avg = adc_code;
adc_acc = adc_avg*ADC_SampleSize;
while (1)
{
OSTimeDlyHMSM(0, 0, 0, 20);
LTC2315_read(&adc_code);
adc_code >>= 16 - LTC2315_bits;
//adc_code >>= 16 - LTC2315_bits - LTC2315_shift;
adc_avg = Data_code_to_avg(adc_code, adc_avg, ADC_SampleSize, &adc_acc);
adc_voltage = LTC2315_code_to_voltage(adc_code, 2, 4.096);
}
}
一周热门 更多>