15届蓝桥杯省赛嵌入式赛前准备
15 届蓝桥杯省赛嵌入式赛前准备
考纲
客观题
电路基础
电子元件
数模电路
工具仪表使用
STM32微控制器
通信总线
传感器应用
ARM微控制器基础
设计题
LED操作
CubeMX中设置PC8~15为GPIO Output(与LCD引脚复用),PD2也为GPIO Output,不需要设置其他的
LED控制:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36/* USER CODE BEGIN PV */
// led
uint8_t ledBuffer = 0;
uint16_t ledPinList[8] = {GPIO_PIN_8, GPIO_PIN_9, GPIO_PIN_10, GPIO_PIN_11, GPIO_PIN_12, GPIO_PIN_13, GPIO_PIN_14, GPIO_PIN_15};
/* USER CODE END PV */
/* USER CODE BEGIN PFP */
void LED_Ctrl(uint8_t ctrl);
/* USER CODE END PFP */
/* USER CODE BEGIN 2 */
LED_Ctrl(0);
HAL_Delay(3000);
for(int i = 0; i < 8; i++) // 功能:LED流水灯
{
ledBuffer = 0;
ledBuffer |= (0x01 << i);
LED_Ctrl(ledBuffer);
HAL_Delay(500);
}
/* USER CODE END 2 */
/* USER CODE BEGIN 4 */
void LED_Ctrl(uint8_t ctrl){
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET); // Unlock
for(int i = 0; i < 8; i++){
HAL_GPIO_WritePin(GPIOC, ledPinList[i], ((ctrl & (0x01 << i)) ? GPIO_PIN_RESET : GPIO_PIN_SET));
}
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); // Lock
}
/* USER CODE END 4 */LED隔500ms闪烁,持续5秒
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64// 在上述代码的基础上增加下面的内容
// main.c
uint8_t errorWarningFlag = 0;
uint16_t errorWarningCount = 0;
uint8_t blinkFlag = 0;
void LED_Blink(void);
ledBuffer = 0;
LED_Ctrl(0);
HAL_Delay(1000);
errorWarningFlag = 1;
while (1)
{
if(blinkFlag){
blinkFlag = 0;
LED_Blink();
}
}
void LED_Blink(void){
ledBuffer ^= 0x01; // 异或,闪烁
LED_Ctrl(ledBuffer);
}
// stm32g4xx_it.c
/* USER CODE BEGIN PV */
// led
extern uint8_t errorWarningFlag;
extern uint16_t errorWarningCount;
extern uint8_t blinkFlag;
/* USER CODE END PV */
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
if(errorWarningFlag){
if(errorWarningCount == 4999){ // 5s
errorWarningFlag = 0;
errorWarningCount = 0;
}else{
errorWarningCount ++;
if(errorWarningCount % 500 == 1){ // 500ms
blinkFlag = 1; // Blink led
}
}
}
/* USER CODE END SysTick_IRQn 1 */
}
STM32G431微控制器内部资源
IO
中断
见串口
ADC
CubeMX添加ADC,选择SingleEnded,添加GPIO_Analog
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
HAL_ADCEx_Calibration_Start(&hadc2, ADC_SINGLE_ENDED);
while (1)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_Start(&hadc2);
HAL_ADC_PollForConversion(&hadc1, 100);
HAL_ADC_PollForConversion(&hadc2, 100);
ADCValue1 = HAL_ADC_GetValue(&hadc1);
ADCValue2 = HAL_ADC_GetValue(&hadc2);
snprintf((char *)str, 20," R37:%d ", ADCValue2);
LCD_DisplayStringLine(Line4, str);
snprintf((char *)str, 20," R38:%d ", ADCValue1);
LCD_DisplayStringLine(Line5, str);
}
I2C
定时器
基础定时
输入捕获
1
2
3
4
5
6
7
8
9
10
11__HAL_TIM_SET_COUNTER(&htim2, 0);
__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
captureValue = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
__HAL_TIM_SET_COUNTER(&htim2, 0);
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
}
输出比较
CubeMX里TIM选择Internal Clock,设置PWM,分频,AutoReload等等
1
2
3
4
5
6
7
8
9void change_freq_duty_cycle(uint16_t freq, float duty_cycle);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
void change_freq_duty_cycle(uint16_t freq, float duty_cycle)
{
__HAL_TIM_SET_AUTORELOAD(&htim3, (1000000 / freq) - 1);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 1000000 / freq * duty_cycle);
}
串口
不定长指令处理
CubeMX配置:USART1,异步,波特率9600其他不改,DMA添加TX和RX,其他保持默认,打开global interrupt
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48// main.c
// UART
uint8_t rxBuffer[20] = {0};
uint8_t txBuffer[20] = {0};
void USER_UART_IRQHandler(UART_HandleTypeDef *huart);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart1, rxBuffer, 20);
void USER_UART_IRQHandler(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
if(__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
{
__HAL_UART_CLEAR_IDLEFLAG(huart);
HAL_UART_DMAStop(huart);
char ret, num;
ret = sscanf((char *)rxBuffer, "R3%c", &num);
if(ret == 1){
if(num == '7' || num == '8' || num == 'a')
{
sprintf((char *)txBuffer, "%c", num);
HAL_UART_Transmit_DMA(&huart1, txBuffer, strlen((char *)txBuffer));
}
}
memset(rxBuffer, 0, sizeof(rxBuffer));
HAL_UART_Receive_DMA(&huart1, rxBuffer, 20);
}
}
}
// stm32g4xx_it.c
extern void USER_UART_IRQHandler(UART_HandleTypeDef *huart);
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
USER_UART_IRQHandler(&huart1);
/* USER CODE END USART1_IRQn 1 */
}
DMA
见串口
按键
独立按键
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66uint8_t Key_Detect(void);
while (1)
{
uint8_t key = Key_Detect();
Key_Process(key);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
uint8_t Key_Detect(void)
{
static uint8_t keyPressedFlag = 0;
if(!keyPressedFlag && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET)
{
HAL_Delay(5);
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET)
{
keyPressedFlag = 1;
return 1;
}
}
if(!keyPressedFlag && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET)
{
HAL_Delay(5);
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET)
{
keyPressedFlag = 1;
return 2;
}
}
if(!keyPressedFlag && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET)
{
HAL_Delay(5);
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET)
{
keyPressedFlag = 1;
return 3;
}
}
if(!keyPressedFlag && HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)
{
HAL_Delay(5);
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)
{
keyPressedFlag = 1;
return 4;
}
}
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_SET &&
HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_SET &&
HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_SET &&
HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET)
{
keyPressedFlag = 0;
}
return 0;
}
单双击处理
长短按处理
TFT-LCD
GPIO配置,相关引脚全部设置为GPIO Output
拷贝
lcd.c
到Src
;拷贝lcd.h
和fonts.h
到Inc
Keil双击主文件夹,添加
lcd.c
main.c
添加1
2
3
4
5
6
7
LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetFontColor(White);
传感器
存储(E2PROM)
导入软件i2c底层文件
添加代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45void eeprom_write_byte(uint8_t data_address, uint8_t data);
uint8_t eeprom_read_byte(uint8_t data_address);
void eeprom_write_byte(uint8_t data_address, uint8_t data)
{
I2CStart();
I2CSendByte(0xA0);
I2CWaitAck();
I2CSendByte(data_address);
I2CWaitAck();
I2CSendByte(data);
I2CWaitAck();
I2CStop();
delay1(500);
}
uint8_t eeprom_read_byte(uint8_t data_address)
{
uint8_t read_data;
I2CStart();
I2CSendByte(0xA0);
I2CWaitAck();
I2CSendByte(data_address);
I2CWaitAck();
I2CStart();
I2CSendByte(0xA1);
I2CWaitAck();
read_data = I2CReceiveByte();
I2CSendNotAck();
I2CStop();
delay1(500);
return read_data;
}
// main.c
I2CInit();
uint8_t count = eeprom_read_byte(0x01);
count ++;
eeprom_write_byte(0x01, count);
数据存储、统计与分析计算
嵌入式综合应用程序设计与调试
注意事项
- 串口发送,没要求的字符不要发(比如”\r\n”),注意发送数量strlen(),去除最后的’\0’,用串口调试器验证一下
- 注意别少单位
- 编程完成后,从头到尾仔细验证一遍功能
- ADC使用前要校准
- 不能使用ARMCC V6编译器,否则会没分,只能用慢慢的V5
- 可以用外部晶振,外部晶振修改为24MHz,HSE经过PLL到达SYSCLK为170MHz(24 -> /6 -> *85 -> /2 -> 170)
- 不要生成单独的外设文件
获奖
获得个人赛省赛一等奖,获得国赛资格。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 MoBlog 子睦的博客!
评论