单片机与外界通信和读取数据需要一些外设模块的支持,例如ADC模块、USART模块、I2C模块、SPI模块等。这些模块分别可以用来读取模拟信号、串口通讯数据、I2C总线上的数据以及SPI总线上的数据。通过对这些模块的配置和调用,我们就可以实现单片机对不同类型数据的读取。
对于模拟信号的读取,我们可以使用ADC模块。在使用ADC模块之前,需要对ADC进行初始化设置。包括选择ADC输入通道、设置参考电压、选择采样时钟源等。初始化完成后,可以开始采样并读取模拟信号的值。在读取完成后,需要对ADC进行关闭和复位操作。
单片机读取模拟信号的示例代码:
// ADC配置void ADC_Init(void)
ADC_InitTypeDef ADC_InitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
// 使能ADC时钟,设置引脚为模拟输入模式
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置ADC转换参数
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
ADC_InitStruct.ADC_ScanConvMode = DISABLE;
ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStruct.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStruct);
// 配置ADC时钟源和采样周期
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_41Cycles5);
ADC_Cmd(ADC1, ENABLE);
// ADC校准
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1));
// 读取模拟信号
int ADC_GetValue(void)
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
return ADC_GetConversionValue(ADC1);
对于串口通讯数据的读取,我们可以使用USART模块。在使用USART模块之前,需要对USART进行初始化设置。包括设置波特率、校验位、数据位、停止位等。初始化完成后,可以开始接收和读取串口数据。在读取完成后,需要对USART进行关闭操作。
单片机读取串口通讯数据的示例代码:
// USART配置void USART_Init(void)
USART_InitTypeDef USART_InitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
// 使能USART时钟和GPIO时钟,设置引脚模式
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置USART波特率、校验位、数据位、停止位等参数
USART_InitStruct.USART_BaudRate = 9600;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Rx;
USART_Init(USART1, &USART_InitStruct);
// 使能USART接收中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);
// 读取串口数据
void USART1_IRQHandler(void)
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
uint8_t data = USART_ReceiveData(USART1);
// 处理接收到的数据
}
// 关闭USART
void USART_DeInit(void)
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
USART_Cmd(USART1, DISABLE);
对于I2C和SPI总线上的数据读取,我们需要使用相应的硬件模块进行通讯。在使用这些模块之前,需要对模块进行初始化设置。包括设置总线时钟、数据传输速率等参数。初始化完成后,可以开始进行数据传输,包括发送和接收。在传输完成后,需要对模块进行关闭操作。
单片机读取I2C和SPI总线上数据的示例代码:
// I2C配置void I2C_Init(void)
I2C_InitTypeDef I2C_InitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
// 使能I2C和GPIO时钟,设置引脚模式
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
// 配置I2C总线时钟、速率等参数
I2C_InitStruct.I2C_ClockSpeed = 100000;
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStruct.I2C_OwnAddress1 = 0x00;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStruct);
I2C_Cmd(I2C1, ENABLE);
// 读取I2C总线上的数据
uint8_t I2C_ReadData(uint8_t devAddr, uint8_t regAddr)
uint8_t data;
// 发送读命令
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, devAddr, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C1, regAddr);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// 读取数据
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, devAddr, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
data = I2C_ReceiveData(I2C1);
I2C_GenerateSTOP(I2C1, ENABLE);
return data;
// 关闭I2C
void I2C_DeInit(void)
I2C_Cmd(I2C1, DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, DISABLE);
// SPI配置
void SPI_Init(void)
SPI_InitTypeDef SPI_InitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
// 使能SPI和GPIO时钟,设置引脚模式
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置SPI总线时钟、速率等参数
SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_Init(SPI1, &SPI_InitStruct);
SPI_Cmd(SPI1, ENABLE);
// 读取SPI总线上的数据
uint8_t SPI_ReadData(uint8_t addr)
uint8_t data;
// 使能SPI传输
GPIO_ResetBits(GPIOA, GPIO_Pin_1);
SPI_I2S_SendData(SPI1, addr);
while(!SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE));
data = SPI_I2S_ReceiveData(SPI1);
GPIO_SetBits(GPIOA, GPIO_Pin_1);
return data;
// 关闭SPI
void SPI_DeInit(void)
SPI_I2S_DeInit(SPI1);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, DISABLE);