蓝桥杯嵌入式国赛备战
1、iic
引脚pb6/pb7
总线上的外设有eeprom和mcp4017
eeprom
- 连续的两次写入之间要加延时
mcp4017
连续的两次写入之间可以不加延时
pb14读取电压
计算公式:v = 3.3 * r_read / (10 + r_read)
r_read = iic_read / 127 * 100(本芯片组织范围是104E,也就是10 * 10^4 = 100KΩ的范围)
void bsp_eeprom_write
(
unsigned char addr,
unsigned char value
)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(value);
I2CWaitAck();
I2CStop();
}
unsigned char bsp_eeprom_read
(
unsigned char addr
)
{
unsigned char ret = 0x00;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
ret = I2CReceiveByte();
I2CSendNotAck();
I2CStop();
return ret;
}
void bsp_mcp4017_write
(
unsigned char value
)
{
I2CStart();
I2CSendByte(0x5e);
I2CWaitAck();
I2CSendByte(value);
I2CWaitAck();
I2CStop();
}
unsigned char bsp_mcp4017_read
(
void
)
{
unsigned char ret = 0x00;
I2CStart();
I2CSendByte(0x5f);
I2CWaitAck();
ret = I2CReceiveByte();
I2CSendNotAck();
I2CStop();
return ret;
}
2、lcd
官方有提供驱动程序,移植到工程中即可
主要考点
- 显示
void LCD_DisplayStringLine(u8 Line, u8 *ptr)
- 屏幕高亮
void bsp_lcd_display_light
(
unsigned char line,
unsigned char *ptr,
unsigned short int color,
unsigned char left,
unsigned char right
)
{
u32 i = 0;
u16 refcolumn = 319;//319;
while ((*ptr != 0) && (i < 20)) // 20
{
if (i >= left && i <= right)
{
unsigned short int old_color = BackColor;
LCD_SetBackColor(color);
LCD_DisplayChar(line, refcolumn, *ptr);
LCD_SetBackColor(old_color);
}
else
{
LCD_DisplayChar(line, refcolumn, *ptr);
}
refcolumn -= 16;
ptr++;
i++;
}
}
- 屏幕翻转
根据手册和给的驱动,我板子是配套使用的是void REG_932X_Init(void)初始化函数。要翻转屏幕,只需改变 相对应的寄存器的值即可
/* 正 */
LCD_WriteReg(R1, 0x0000);
LCD_WriteReg(R96, 0x2700);
/* 反 */
LCD_WriteReg(R1, 0x0100);
LCD_WriteReg(R96, 0xA700);
3、led
led的引脚会和lcd会冲突,这里我使用了缓存保存led的状态
- 驱动
#include "./led/bsp_led.h"
#include "gpio.h"
static unsigned char led_state = 0x00;
void bsp_led_init
(
void
)
{
HAL_GPIO_WritePin(GPIOC, 0xff00, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
led_state = 0x00;
}
void bsp_led_fresh
(
void
)
{
unsigned int buf;
buf = GPIOC->ODR;
HAL_GPIO_WritePin(GPIOC, 0xff00, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, (led_state << 8), GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
GPIOC->ODR = buf;
}
void bsp_led_open
(
unsigned char i
)
{
led_state |= (1 << i);
bsp_led_fresh();
}
void bsp_led_close
(
unsigned char i
)
{
led_state &= ~(1 << i);
bsp_led_fresh();
}
void bsp_led_flip
(
unsigned char i
)
{
if ((led_state & (1 << i)) != 0)
{
bsp_led_close(i);
}
else
{
bsp_led_open(i);
}
}
- 开关led、闪烁led、定时led
typedef struct stru_led
{
unsigned char state;
unsigned char flag;
unsigned char mode;
unsigned int count;
unsigned int interval;
unsigned int time;
} stru_led_t;
void led_proc
(
stru_led_t led[]
)
{
for (int i = 0; i < 8; i++)
{
switch (led[i].mode)
{
/* 开关led */
case 0:
if (led[i].state == 0)
{
if (led[i].flag == 1)
{
bsp_led_open(i);
led[i].state = 1;
}
}
else if (led[i].state == 1)
{
if (led[i].flag == 0)
{
bsp_led_close(i);
led[i].state = 0;
}
}
break;
/* led定时 */
case 1:
if (led[i].state == 0)
{
if (led[i].flag == 1)
{
bsp_led_open(i);
led[i].state = 1;
}
}
else if (led[i].state == 1)
{
if (led[i].flag == 1)
{
led[i].time--;
}
if (led[i].time == 0)
{
bsp_led_close(i);
led[i].state = 0;
led[i].flag = 0;
}
}
break;
/* led闪烁 */
case 2:
if (led[i].flag == 1)
{
if (led[i].count % led[i].interval == 0)
{
bsp_led_flip(i);
led[i].state = 1;
}
if (++(led[i].count) == 1000)
{
led[i].count = 0;
}
}
else
{
if (led[i].state == 1)
{
bsp_led_close(i);
led[i].state = 0;
led[i].count = 0;
}
}
break;
}
}
}
4、key
独立按键、长短按键、单双击
- 独立按键and长短按键
void bsp_key_scanf
(
stru_key_ret_t key_ret[]
)
{
static stru_key_state_t key[4] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
key[0].pin_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
key[1].pin_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
key[2].pin_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);
key[3].pin_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
for (int i = 0; i < 4; i++)
{
switch (key[i].flag_state)
{
case 0:
if (key[i].pin_state == GPIO_PIN_RESET)
{
key[i].time = 0;
key[i].flag_state = 1;
}
break;
case 1:
if (key[i].pin_state == GPIO_PIN_RESET)
{
key[i].time++;
key[i].flag_state = 2;
}
else
{
key[i].flag_state = 0;
}
break;
case 2:
if (key[i].pin_state == GPIO_PIN_RESET)
{
key[i].time++;
}
else
{
if (key[i].time > LONG_TIME)
{
key_ret[i].long_flag = 1;
}
else
{
key_ret[i].one_flag = 1;
}
key[i].flag_state = 0;
}
break;
}
}
}
- 单双击
5、usart
考纲写明考察,串口(不定长指令处理),这里使用的是空闲中断的接收方式,没有使用DMA
注意点:要选择正确的io口,板子的下载口有用到串口1(pa9/pa10脚),但是串口1默认的不是pa9/pa10
void bsp_usart_init
(
UART_HandleTypeDef *huart,
stru_usart_t *buf
)
{
HAL_UART_Receive_IT(huart, (*buf).buf, USART_BUF_SIZE);
__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
__HAL_UART_CLEAR_IDLEFLAG(huart);
}
void bsp_usart_handler
(
UART_HandleTypeDef *huart,
stru_usart_t *buf
)
{
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET)
{
(*buf).flag = 1;
(*buf).len = USART_BUF_SIZE - (*huart).RxXferCount;
__HAL_UART_CLEAR_IDLEFLAG(huart);
HAL_UART_AbortReceive_IT(huart);
HAL_UART_Receive_IT(huart, (*buf).buf, USART_BUF_SIZE);
}
}
void bsp_usart_buf_clear
(
stru_usart_t *buf
)
{
memset(buf, 0, sizeof(stru_usart_t));
}
6、adc
adc多通道采集
HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
for (int i = 0; i < 2; i++)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 20);
if (i == 0)
{
data.pb14 = HAL_ADC_GetValue(&hadc1) * 3.3 / 4096;
}
else
{
data.pb12 = HAL_ADC_GetValue(&hadc1) * 3.3 / 4096;
}
}
7、输入捕获
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);
if (htim->Instance == TIM3)
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
unsigned int all_tick = 0, ris_tick = 0;
all_tick = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
ris_tick = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
__HAL_TIM_SetCounter(htim, 0);
data.freq_pb4 = (80000000 / 80) / (all_tick + 1);
data.duty_pb4 = (ris_tick + 1) * 100 / (all_tick + 1);
HAL_TIM_IC_Start_IT(htim, TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(htim, TIM_CHANNEL_2);
}
}
8、pwm
HAL_TIM_PWM_Start(&htim17, TIM_CHANNEL_1);
__HAL_TIM_SetCompare(&htim17, TIM_CHANNEL_1, 1000);