根据引脚勾选通道
参数只需更改采样周期,其它默认即可
uint16_t ADC_IN_1(void) //ADC采集程序
{
HAL_ADC_Start(&hadc1);//开始ADC采集
HAL_ADC_PollForConversion(&hadc1,500);//等待采集结束
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))//读取ADC完成标志位
{
return HAL_ADC_GetValue(&hadc1);//读出ADC数值
}
return 0;
}
HAL_ADCEx_Calibration_Start(&hadc1);//ADC采样校准
uint16_t adc_num;
adc_num = ADC_IN_1();
ADC读出的值为0-4096,对应0-3.3V
开启I2C
复制fonts.h、ssd1306.h到Core/Inc目录,复制fonts.c ssd1306.c到Core/Src目录
ssd1306.7z
头文件
#include "fonts.h"
#include "ssd1306.h"
初始化
SSD1306_Init();
char snum[5];
主循环中
for ( int x = 1; x <= 10000 ; x++ )
{
itoa(x, snum, 10);
SSD1306_GotoXY (30, 30); // 4 DIGIS
SSD1306_Puts (snum, &Font_16x26, 1);
SSD1306_UpdateScreen();
HAL_Delay (500);
}
定时时间计算公式:
根据定时器时钟的频率,比如时钟的频率是72MHZ,可以理解为一秒钟STM32会自己数72M次,预分频系数就是将频率分割,比如分频系数是72,则该时钟的频率会变成72MHZ/72=1MHZ,但是在设置的时候要注意,数值应该是72-1。假定分频系数是72-1,那么频率变成1MHZ,也就意味着STM32在一秒钟会数1M次,即1us数一次。
接下来就是确定预装载值,比如需要定时1ms,由于1ms=1us*1000,那么预装载值就是1000-1;如此类推,在预分频系数确定的情况下,定时的时长就由预装载值确定了。
例如:
开启定时器
HAL_TIM_Base_Start_IT(&htim2);
回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
if(htim==(&htim2)){
LED_1_Contrary();
}
}
获取定时器计数值
__HAL_TIM_GET_COUNTER(&htim);
设置好i2c之后,就可以用了
设置SPI,这些参数是芯片规定的
片选引脚设置
复制驱动程序
依赖delay_us函数,把delay驱动程序也复制进来
引入头文件
#include "../../icode/w25q128/w25qxx.h"
HAL_Dalay(500);
W25QXX_Init();
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(KEY_1()){
EX_FLASH_BUF[0] = W25QXX_ReadID();
printf("芯片ID:%x \n\r",EX_FLASH_BUF[0]);
}
if(KEY_2()){
W25QXX_Read(EX_FLASH_BUF,EX_FLASH_ADD,1);
EX_FLASH_BUF[0]++;
if(EX_FLASH_BUF[0]>200)EX_FLASH_BUF[0]=0;
W25QXX_Write(EX_FLASH_BUF,EX_FLASH_ADD,1);
printf("读出0x00地址数据:%d \n\r",EX_FLASH_BUF[0]);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
HAL库的延时函数HAL_Delay()有两个问题:
所以需要自己写一个延时函数:
void delay_us(uint32_t us) //利用CPU循环实现的非精准应用的微秒延时函数
{
uint32_t delay = (HAL_RCC_GetHCLKFreq() / 8000000 * us); //使用HAL_RCC_GetHCLKFreq()函数获取主频值,经算法得到1微秒的循环次数
while (delay--); //循环delay次,达到1微秒延时
}
以__weak开头的函数,如果我们没有实现它,就执行他,如果我们声明了一个同名函数,就以我们的为准。
所以我们只需要定义一个
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
if(GPIO_Pin == KEY1_Pin){
LED_1_Contrary();
}
}
void LED_1(uint8_t a)//LED1独立控制函数(0为熄灭,其他值为点亮)
{
if(a)HAL_GPIO_WritePin(GPIOB,LED1_Pin,GPIO_PIN_SET);
else HAL_GPIO_WritePin(GPIOB,LED1_Pin,GPIO_PIN_RESET);
}
uint8_t KEY_1(void)
{
uint8_t a;
a=0;
if(HAL_GPIO_ReadPin(GPIOA,KEY1_Pin)==GPIO_PIN_RESET){
//HAL_Delay(20);
delay_us(2000);
if(HAL_GPIO_ReadPin(GPIOA,KEY1_Pin)==GPIO_PIN_RESET){
a=1;
}
}
while(HAL_GPIO_ReadPin(GPIOA,KEY1_Pin)==GPIO_PIN_RESET);
delay_us(2000);
return a;
}
周期的设置方法与定时器相同,
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);
/* USER CODE END 2 */
while (pwmVal< 500)
{
pwmVal++;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_2, pwmVal);
HAL_Delay(1);
}
while (pwmVal)
{
pwmVal--;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_2, pwmVal);
HAL_Delay(1);
}
HAL_Delay(200);
排除syscalls.c
把retarget.h拷贝到Core/Inc,把retarget.c拷贝到Core/Src
头文件引入
#include "../inc/retarget.h"
RetargetInit(&huart1);
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(KEY_1()){
printf("KEY1\r\n");
}
if(KEY_2()){
printf("KEY2\r\n");
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */