江科大STM32

STM32 简�?







片上资源

系统结构

引脚定义

启动配置

最小系统电�?


GPIO

GPIO基本结构

端口位结�?






硬件电路的驱动方�?

LED闪烁实验

int main(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); while (1) { GPIO_ResetBits(GPIOA, GPIO_Pin_0); Delay_ms(500); GPIO_SetBits(GPIOA, GPIO_Pin_0); Delay_ms(500); GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); Delay_ms(500); GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); Delay_ms(500); GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0); Delay_ms(500); GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1); Delay_ms(500); } }
|
LED流水�?

int main(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); while (1) { GPIO_Write(GPIOA, ~0x0001); Delay_ms(100); GPIO_Write(GPIOA, ~0x0002); Delay_ms(100); GPIO_Write(GPIOA, ~0x0004); Delay_ms(100); GPIO_Write(GPIOA, ~0x0008); Delay_ms(100); GPIO_Write(GPIOA, ~0x0010); Delay_ms(100); GPIO_Write(GPIOA, ~0x0020); Delay_ms(100); GPIO_Write(GPIOA, ~0x0040); Delay_ms(100); GPIO_Write(GPIOA, ~0x0080); Delay_ms(100); } }
|
蜂鸣�?

int main(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); while (1) { GPIO_ResetBits(GPIOB, GPIO_Pin_12); Delay_ms(100); GPIO_SetBits(GPIOB, GPIO_Pin_12); Delay_ms(100); GPIO_ResetBits(GPIOB, GPIO_Pin_12); Delay_ms(100); GPIO_SetBits(GPIOB, GPIO_Pin_12); Delay_ms(700); } }
|
环境搭建
新建工程

工程架构

GPIO输出

GPIO基本结构

GPIO端口位结�?

GPIO输入


*元器件上拉输入模式在没有输入时默认为低电�?


按键控制LED

关键代码
void Key_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); }
uint8_t Key_GetNum(void) { uint8_t KeyNum = 0; if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0) { Delay_ms(20); while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0); Delay_ms(20); KeyNum = 1; } if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0) { Delay_ms(20); while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0); Delay_ms(20); KeyNum = 2; } return KeyNum; }
|
光敏传感器控制蜂鸣器

关键代码
void LightSensor_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); }
uint8_t LightSensor_Get(void) { return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13); }
|
STM32 八种输入输出模式总结
1. GPIO_MODE_AIN 模拟输入
输入信号不经施密特触发器直接接入�?*输入信号为模拟量**而非数字量,其余输入方式输入数字量�?
2. GPIO_MODE_IN_FLOATING 浮空输入
输入信号经过施密特触发器接入输入数据存储器�?*当无信号输入时,电压不确�?*。因为浮空输入既高阻输入,可以认为输入端口阻抗无穷大,这样可以检测到微弱的信号。(相当于电压表测电压,如果电压表内阻不够大而外部阻抗比较大,则电压表分压会比较小)。此时输入高电平即高电平,输入低电平即低电平。但是外界没有输入时输入电平却容易受到外界电磁以及各种玄学干扰的影响。如按键采用浮空输入,则在按键按下时输入电平为低,但是当松开按键时输入端口悬空,外界有微弱的干扰都会被端口检测到。此时端口可能高,也可能低�?
3. GPIO_MODE_IPD 下拉输入
浮空输入在外界没有输入时状态不确定,可能对电路造成干扰。为了使得电路更加稳定,不出现没有输入时端口的输入数据被干扰 (比如手碰一下电压就发生变化)。这时就需要下拉电阻(或上拉电阻),此电阻与端口输入阻抗相比仍然较小。有输入信号时端口读取输入信号,**无输入信号时端口电平被拉到低电平(高电平�?*�?
4. GPIO_MODE_IPU 上拉输入
上拉输入与下拉输入类似,只是无输入信号时端口电平被拉到高电平。例如按键信号,当按下时输入低电平,松开时电平被拉到高电平。这样就不会出现按键松开时端口电平不确定的情况。即不知道时按下还是松开�?
5. GPIO-MODE_OUT_OD 开漏输�?
开漏输出即**漏极开路输�?*。这种输出方式指场效应管漏极开路输出�?*需要接上拉电阻才能输出1**。漏极经上拉电阻接到电源,栅极输�?时,场效应管截止(阻抗无线大),电压被分到场效应管上,此时输出为1。当栅极输出1时,场效应管导通,输出端口相当于接地,此时输出0。开漏输出高电平时是由外接电源输出的,因此可以实现高于输出端口电压的输出。可以实现电平的转换�?*开漏输出可以实现线与功�?*,方法是多个输出共接一个上拉电阻。但是漏极开路输�?*上升沿慢**,因为上升沿是外接电源对上拉电阻以及外接负载充电。当上拉电阻较大或者负载容性较大时时间常数较大,充电较慢�?*需要较快反映时可以采用下降沿触�?*,此时没有电阻接入,电路的时间常数较小,充电较快�?
6. GPIO_MODE_OUT_PP 推挽输出
推挽输出既可以输�?,又可以输出0。但是无法调节输出电压,因为输出高低电平均为三极管输入端电压,此电压在由芯片内部供电,无法改变。推挽输出任意时刻只有一路工作。上图为输出高电平时电路工作状态。只有三极管导通电阻,无外接电阻。因此推挽输�?*损耗小、速度�?*�?
7. GPIO_MODE_AF_OD 复用开漏输�?
STM32单片机内部有其他的外设,比如定时器、DAC等。复用开漏输出与普通开漏输出区别在于,开漏输出输出的是输出数据寄存器中的数据�?*复用开漏输出输出的是来自外设的数据**�?
8. GOIO_MODE_AF_PP 复用推挽输出
*复用推挽输出原理与复用开漏输出原理相�?
OLED调试驱动


中断系统



NVIC嵌套中断向量控制�?


EXTI外部中断


配置外设中断的基本流�?
- 配置RCC, 打开涉及的外设时�?2. 配置GPIO
- 配置AFIO
- 配置EXTI
- 配置NVIC

AFIO复用IO�?


旋转编码�?

红外传感器计�?
void CountSensor_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14); EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line = EXTI_Line14; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_Init(&EXTI_InitStructure); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_Init(&NVIC_InitStructure); }
uint16_t CountSensor_Get(void) { return CountSensor_Count; }
void EXTI15_10_IRQHandler(void) { if (EXTI_GetITStatus(EXTI_Line14) == SET) {
|
STM32�?中断函数的名字是固定�? 参见start文件中的定义
旋转编码器计�?
void Encoder_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1); EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_Init(&EXTI_InitStructure); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_Init(&NVIC_InitStructure); }
int16_t Encoder_Get(void) { int16_t Temp; Temp = Encoder_Count; Encoder_Count = 0; return Temp; }
void EXTI0_IRQHandler(void) { if (EXTI_GetITStatus(EXTI_Line0) == SET) {
|
STM32�?中断函数的名字是固定�? 参见start文件中的定义
__Vectors DCD __initial_sp DCD Reset_Handler DCD NMI_Handler DCD HardFault_Handler DCD MemManage_Handler DCD BusFault_Handler DCD UsageFault_Handler DCD 0 DCD 0 DCD 0 DCD 0 DCD SVC_Handler DCD DebugMon_Handler DCD 0 DCD PendSV_Handler DCD SysTick_Handler
DCD WWDG_IRQHandler DCD PVD_IRQHandler DCD TAMPER_IRQHandler DCD RTC_IRQHandler DCD FLASH_IRQHandler DCD RCC_IRQHandler DCD EXTI0_IRQHandler DCD EXTI1_IRQHandler DCD EXTI2_IRQHandler DCD EXTI3_IRQHandler DCD EXTI4_IRQHandler DCD DMA1_Channel1_IRQHandler DCD DMA1_Channel2_IRQHandler DCD DMA1_Channel3_IRQHandler DCD DMA1_Channel4_IRQHandler DCD DMA1_Channel5_IRQHandler DCD DMA1_Channel6_IRQHandler DCD DMA1_Channel7_IRQHandler DCD ADC1_2_IRQHandler DCD USB_HP_CAN1_TX_IRQHandler DCD USB_LP_CAN1_RX0_IRQHandler DCD CAN1_RX1_IRQHandler DCD CAN1_SCE_IRQHandler DCD EXTI9_5_IRQHandler DCD TIM1_BRK_IRQHandler DCD TIM1_UP_IRQHandler DCD TIM1_TRG_COM_IRQHandler DCD TIM1_CC_IRQHandler DCD TIM2_IRQHandler DCD TIM3_IRQHandler DCD TIM4_IRQHandler DCD I2C1_EV_IRQHandler DCD I2C1_ER_IRQHandler DCD I2C2_EV_IRQHandler DCD I2C2_ER_IRQHandler DCD SPI1_IRQHandler DCD SPI2_IRQHandler DCD USART1_IRQHandler DCD USART2_IRQHandler DCD USART3_IRQHandler DCD EXTI15_10_IRQHandler DCD RTCAlarm_IRQHandler DCD USBWakeUp_IRQHandler
|
定时器TIM





定时中断

定时器时�?




RCC时钟�?

定时器定时中�?
void Timer_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_InternalClockConfig(TIM2); TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1; TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1; TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); TIM_ClearFlag(TIM2, TIM_FLAG_Update); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_Init(&NVIC_InitStructure); TIM_Cmd(TIM2, ENABLE); }
|
定时器外部时�?> 用IO口模拟外部时钟源

void Timer_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F); TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 10 - 1; TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1; TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); TIM_ClearFlag(TIM2, TIM_FLAG_Update); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_Init(&NVIC_InitStructure); TIM_Cmd(TIM2, ENABLE); }
uint16_t Timer_GetCounter(void) { return TIM_GetCounter(TIM2); }
|
TIM输出比较








(相当于把PWM当成通讯协议来用, 舵机里面自带驱动电路)
PWM驱动实验

void PWM_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_InternalClockConfig(TIM2); TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OC1Init(TIM2, &TIM_OCInitStructure); TIM_Cmd(TIM2, ENABLE); }
void PWM_SetCompare1(uint16_t Compare) { TIM_SetCompare1(TIM2, Compare); }
|
TIM输入捕获


*测频法适合高频, 测周法适合低频, 以中界频率为�?




PWMI模式测频�?占空�?
void IC_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_InternalClockConfig(TIM3); TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure); TIM_ICInitTypeDef TIM_ICInitStructure; TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM_ICInitStructure.TIM_ICFilter = 0xF; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); TIM_Cmd(TIM3, ENABLE); }
uint32_t IC_GetFreq(void) { return 1000000 / (TIM_GetCapture1(TIM3) + 1); }
uint32_t IC_GetDuty(void) { return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1); }
|
编码器接�?





编码器接口测�?

void Encoder_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1; TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure); TIM_ICInitTypeDef TIM_ICInitStructure; TIM_ICStructInit(&TIM_ICInitStructure); TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM_ICInitStructure.TIM_ICFilter = 0xF; TIM_ICInit(TIM3, &TIM_ICInitStructure); TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; TIM_ICInitStructure.TIM_ICFilter = 0xF; TIM_ICInit(TIM3, &TIM_ICInitStructure); TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); TIM_Cmd(TIM3, ENABLE); }
int16_t Encoder_Get(void) { int16_t Temp; Temp = TIM_GetCounter(TIM3); TIM_SetCounter(TIM3, 0); return Temp; }
|
ADC模数转换



ADC基本结构

输入通道

转换模式
- 单次转换,非扫描模式

- 连续转换,非扫描模式

- 单次转换,扫描模�?

- 连续转换,扫描模�?

- …


AD单通道
void AD_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_ADCCLKConfig(RCC_PCLK2_Div6); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure); ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1) == SET); ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1) == SET); }
uint16_t AD_GetValue(void) { ADC_SoftwareStartConvCmd(ADC1, ENABLE); while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); return ADC_GetConversionValue(ADC1); }
|
DMA





高位补零/高位舍弃
DMA数据转运

ADC扫描模式+DMA

存储器映�?


DMA工作的条�?1. 转运计数器大�?
2. 触发源有触发信号
3. DMA使能
DMA数据转运
uint16_t MyDMA_Size;
void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size) { MyDMA_Size = Size; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_InitTypeDef DMA_InitStructure; DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable; DMA_InitStructure.DMA_MemoryBaseAddr = AddrB; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = Size; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_M2M = DMA_M2M_Enable; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_Init(DMA1_Channel1, &DMA_InitStructure); DMA_Cmd(DMA1_Channel1, DISABLE); }
void MyDMA_Transfer(void) { DMA_Cmd(DMA1_Channel1, DISABLE); DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size); DMA_Cmd(DMA1_Channel1, ENABLE); while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET); DMA_ClearFlag(DMA1_FLAG_TC1); }
|
DMA+AD多通道
uint16_t AD_Value[4];
void AD_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); RCC_ADCCLKConfig(RCC_PCLK2_Div6); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5); ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_NbrOfChannel = 4; ADC_Init(ADC1, &ADC_InitStructure); DMA_InitTypeDef DMA_InitStructure; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 4; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_Init(DMA1_Channel1, &DMA_InitStructure); DMA_Cmd(DMA1_Channel1, ENABLE); ADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1) == SET); ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1) == SET); ADC_SoftwareStartConvCmd(ADC1, ENABLE); }
|
串口通信




USART




串口发�?接收
void Serial_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_Structure; GPIO_Structure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Structure.GPIO_Pin = GPIO_Pin_9; GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_Structure); GPIO_Structure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Structure.GPIO_Pin = GPIO_Pin_10; GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_Structure); USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_Init(USART1, &USART_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_Init(&NVIC_InitStructure); USART_Cmd(USART1, ENABLE); }
void Serial_ByteSend(uint8_t byte) { USART_SendData(USART1, byte); while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); }
{ char String[100]; va_list arg; va_start(arg, format); vsprintf(String, format, arg); va_end(arg); Serial_SendString(String); }
|
Hex/文本数据�?


数据包接�?


串口发送文本数据包
状态机核心代码
void USART1_IRQHandler(void) { static uint8_t RxState = 0; static uint8_t pRxPacket = 0; if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET) { uint8_t RxData = USART_ReceiveData(USART1); if(RxState == 0) { if(RxData == '@') { RxState = 1; pRxPacket = 0; } } else if(RxState == 1) { if(RxData == '\r') { RxState = 2; } else { Serial_RxPacket[pRxPacket] = RxData; pRxPacket ++; }
} else if(RxState == 2) { if(RxData == '\n') { RxState = 0; Serial_RxPacket[pRxPacket] = '\0'; Serial_RxFlag = 1; } } USART_ClearITPendingBit(USART1, USART_IT_RXNE); } }
|
I2C通信

I2C时序单元




I2C时序



MPU6050



软件I2C读写MPU6050
控制电平
{ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_Structure; GPIO_Structure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_Structure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_Structure); GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11); }
|
void MyI2C_W_SCL(uint8_t BitValue) { GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue); Delay_us(10); }
void MyI2C_W_SDA(uint8_t BitValue) { GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValue); Delay_us(10); }
uint8_t MyI2C_R_SDA(void) { uint8_t BitValue; BitValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11); Delay_us(10); return BitValue; }
|
I2C基本时序单元
void MyI2C_Start(void) { MyI2C_W_SCL(1); MyI2C_W_SDA(1); MyI2C_W_SDA(0); MyI2C_W_SCL(0);
}
void MyI2C_Stop(void) { MyI2C_W_SDA(0); MyI2C_W_SCL(1); MyI2C_W_SDA(1); }
void MyI2C_SendByte(uint8_t Byte) { uint8_t i = 0; for(i=0; i<8; i++) { MyI2C_W_SDA(Byte & (0x80 >> i)); MyI2C_W_SCL(1); MyI2C_W_SCL(0); } }
uint8_t MyI2C_ReceiveByte(void) { uint8_t i, Byte = 0x00; MyI2C_W_SDA(1); for(i=0; i<8; i++) { MyI2C_W_SCL(1); if(MyI2C_R_SDA() == 1) {Byte |= (0x80 >> i);} MyI2C_W_SCL(0); } return Byte; }
void MyI2C_SendAck(uint8_t AckBit) { MyI2C_W_SDA(AckBit); MyI2C_W_SCL(1); MyI2C_W_SCL(0); }
uint8_t MyI2C_ReceiveAck(void) { uint8_t AckBit; MyI2C_W_SDA(1); MyI2C_W_SCL(1); AckBit = MyI2C_R_SDA(); MyI2C_W_SCL(0); return AckBit; }
|
I2C时序
void MPU6050_WriteReg(uint8_t RegAddr, uint8_t Data) { MyI2C_Start(); MyI2C_SendByte(MPU6050_ADDR); MyI2C_ReceiveAck(); MyI2C_SendByte(RegAddr); MyI2C_ReceiveAck(); MyI2C_SendByte(Data); MyI2C_ReceiveAck(); MyI2C_Stop(); }
uint8_t MPU6050_ReadReg(uint8_t RegAddr) { uint8_t Data; MyI2C_Start(); MyI2C_SendByte(MPU6050_ADDR); MyI2C_ReceiveAck(); MyI2C_SendByte(RegAddr); MyI2C_ReceiveAck(); MyI2C_Start(); MyI2C_SendByte(MPU6050_ADDR | 0x01); MyI2C_ReceiveAck(); Data = MyI2C_ReceiveByte(); MyI2C_SendAck(1); MyI2C_Stop(); return Data; }
|
MPU6050
void MPU6050_Init(void) { MyI2C_Init(); MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01); MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00); MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09); MPU6050_WriteReg(MPU6050_CONFIG, 0x06); MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18); MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18); }
uint8_t MPU6050_GetID(void) { return MPU6050_ReadReg(MPU6050_WHO_AM_I); }
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, \ int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ) { uint16_t DataH, DataL; DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H); DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L); *AccX = (DataH << 8) | (DataL); DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H); DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L); *AccY = (DataH << 8) | (DataL); DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H); DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L); *AccZ = (DataH << 8) | (DataL); DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H); DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L); *GyroX = (DataH << 8) | (DataL); DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H); DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L); *GyroY = (DataH << 8) | (DataL); DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H); DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L); *GyroZ = (DataH << 8) | (DataL);
}
|
STM32 I2C外设



传送流�?


I2C外设实验
硬件部分核心代码(业务逻辑层保持不变)
void MPU6050_WriteReg(uint8_t RegAddr, uint8_t Data) {
I2C_GenerateSTART(I2C2, ENABLE); while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS); I2C_Send7bitAddress(I2C2, MPU6050_ADDR, I2C_Direction_Transmitter); while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS); I2C_SendData(I2C2, RegAddr); while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);
I2C_SendData(I2C2, Data); while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS);
I2C_GenerateSTOP(I2C2, ENABLE); }
uint8_t MPU6050_ReadReg(uint8_t RegAddr) { uint8_t Data;
I2C_GenerateSTART(I2C2, ENABLE); while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS); I2C_Send7bitAddress(I2C2, MPU6050_ADDR, I2C_Direction_Transmitter); while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS); I2C_SendData(I2C2, RegAddr); while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);
I2C_GenerateSTART(I2C2, ENABLE); while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);
I2C_Send7bitAddress(I2C2, MPU6050_ADDR, I2C_Direction_Receiver); while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS); I2C_AcknowledgeConfig(I2C2, DISABLE); I2C_GenerateSTOP(I2C2, ENABLE); while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS); Data = I2C_ReceiveData(I2C2); return Data; }
void MPU6050_Init(void) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_Structure; GPIO_Structure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_Structure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_Structure); GPIO_Init(GPIOB, &GPIO_Structure); I2C_InitTypeDef I2C_InitStructure; I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_ClockSpeed = 50000; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 = 0x00; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_Init(I2C2, &I2C_InitStructure); I2C_Cmd(I2C2, ENABLE);
MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01); MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00); MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09); MPU6050_WriteReg(MPU6050_CONFIG, 0x06); MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18); MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18); }
|
SPI通信



基本时序单元





SPI时序




W25Q64简�?



Flash操作事项


SPI软件读写实验
对电平操作的封装
void MySPI_W_SS(uint8_t bitValue) { GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)bitValue); }
void MySPI_W_SCK(uint8_t bitValue) { GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)bitValue); }
void MySPI_W_MOSI(uint8_t bitValue) { GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)bitValue); }
uint8_t MySPI_R_MISO(void) { return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6); }
|
SPI时序
void MySPI_Start(void) { MySPI_W_SS(0); }
void MySPI_Stop(void) { MySPI_W_SS(1); }
uint8_t MySPI_SwapByte(uint8_t ByteSend) { uint8_t ByteRecive=0x00; uint8_t i; for(i=0; i<8; i++) { MySPI_W_MOSI(ByteSend & (0x80 >> i)); MySPI_W_SCK(1); if(MySPI_R_MISO() == 1) { ByteRecive |= (0x80 >> i); } MySPI_W_SCK(0); } return ByteRecive; }
|
W25Q64操作时序
void W25Q64_Init(void) { MySPI_Init(); }
void W25Q64_ReadID(uint8_t *MID, uint16_t *DID) { MySPI_Start(); MySPI_SwapByte(W25Q64_JEDEC_ID); *MID = MySPI_SwapByte(W25Q64_DUMMY_BYTE); *DID = MySPI_SwapByte(W25Q64_DUMMY_BYTE); *DID <<= 8; *DID |= MySPI_SwapByte(W25Q64_DUMMY_BYTE); MySPI_Stop(); }
void W25Q64_WriteEnable(void) { MySPI_Start(); MySPI_SwapByte(W25Q64_WRITE_ENABLE); MySPI_Stop(); }
void W25Q64_WaitBusy(void) { MySPI_Start(); MySPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1); uint32_t Timeout = 100000; while((MySPI_SwapByte(W25Q64_DUMMY_BYTE) & 0x01) == 0x01) { Timeout --; if(Timeout==0) break; } MySPI_Stop(); }
void W25Q64_PageProgram(uint32_t Address ,uint8_t *DataArray, uint16_t count) { W25Q64_WriteEnable(); MySPI_Start(); MySPI_SwapByte(W25Q64_PAGE_PROGRAM); MySPI_SwapByte(Address>>16); MySPI_SwapByte(Address>>8); MySPI_SwapByte(Address); uint16_t i=0; for(i=0; i<count; i++) { MySPI_SwapByte(DataArray[i]); } MySPI_Stop(); W25Q64_WaitBusy(); }
void W25Q64_SectorErase(uint32_t Address) { W25Q64_WriteEnable(); MySPI_Start(); MySPI_SwapByte(W25Q64_SECTOR_ERASE_4KB); MySPI_SwapByte(Address>>16); MySPI_SwapByte(Address>>8); MySPI_SwapByte(Address); MySPI_Stop(); W25Q64_WaitBusy(); }
void W25Q64_ReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count) { uint32_t i; MySPI_Start(); MySPI_SwapByte(W25Q64_READ_DATA); MySPI_SwapByte(Address>>16); MySPI_SwapByte(Address>>8); MySPI_SwapByte(Address); for(i=0; i<Count; i++) { DataArray[i] = MySPI_SwapByte(W25Q64_DUMMY_BYTE); } MySPI_Stop(); }
|
SPI外设




SPI硬件通信实验
通信逻辑方面不变, 改变的是底层通信的代�? 用硬件电路实�?改变�?个函数MySPI_Init uint8_t MySPI_SwapByte(uint8_t ByteSend) `
void MySPI_W_SS(uint8_t bitValue) { GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)bitValue); }
void MySPI_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); GPIO_InitTypeDef GPIO_Structure; GPIO_Structure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Structure.GPIO_Pin = GPIO_Pin_4; GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_Structure); GPIO_Structure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Structure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7; GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_Structure);
GPIO_Structure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Structure.GPIO_Pin = GPIO_Pin_6; GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_Structure); SPI_InitTypeDef SPI_InitStructure; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); MySPI_W_SS(1); }
void MySPI_Start(void) { MySPI_W_SS(0); }
void MySPI_Stop(void) { MySPI_W_SS(1); }
uint8_t MySPI_SwapByte(uint8_t ByteSend) { while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != SET); SPI_I2S_SendData(SPI1, ByteSend); while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != SET); return SPI_I2S_ReceiveData(SPI1); }
|