---
title: 北農程式實習
lang: zh_TW
description: 北農程式實習
---
[](https://hackmd.io/FW2ksRR5Rneynl3fHieuIg)
:::info
最後修訂: 2024/05/13
:::
---
[toc]
<details>
<summary>相關連結</summary>
- [Github](https://github.com/a3510377)
</details>
# STM32
> 可能有部分程式有問題或不完整,請告知 [猴子 (*Gmail*)](mailto:a102009102009@gmail.com)
> [name=猴子]
## 第一章
### 兩顆 LED 輪流閃爍 0.5s
<details>
<summary>展開程式</summary>
```cpp=
while (1) {
for (uint8_t i = 0; i <= 1; i++) {
HAL_GPIO_WritePin(GPIOC, 1 << i, GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOC, 1 << i, GPIO_PIN_RESET);
}
}
```
```cpp=
while (1) {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
}
```
</details>
### 16 顆 LED 霹靂燈,左右旋 0.2s
<details>
<summary>展開程式</summary>
```cpp=
# define abs(x) ((x) > 0 ? (x) : -(x))
while (1) {
for (int8_t i = -15; i < 15; i++) {
GPIOC->ODR = 1 << abs(i);
HAL_Delay(200);
}
}
```
</details>
<!-- // Use BSRR to prevent interrupts
GPIOC->BSRR = (~pin << 16) | pin; -->
### 8 顆 LED 漸增在漸減 - 建表法,左右旋 0.2s
<details>
<summary>展開程式</summary>
```cpp=
const uint8_t LED[] = {0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f,
0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03};
const uint8_t LED_LEN = sizeof(LED) / sizeof(uint8_t);
while (1) {
for (uint8_t i = 0; i < LED_LEN; i++) {
GPIOC->ODR = LED[i];
HAL_Delay(200);
}
}
```
</details>
### 左右旋 - 建表法 & 中斷
<details>
<summary>展開程式</summary>
```cpp=
#define USE_BSRR
const uint8_t LED[] = {0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f,
0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03};
int timercnt, step;
HAL_TIM_Base_Start_IT(&htim6);
while (1) {
if (!timercnt) {
timercnt = 300;
step = (step + 1) % 14;
}
GPIOC->ODR = LED[step];
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (timercnt > 0) timercnt--;
}
```
</details>
### 8顆 LED速度變快
<details>
<summary>展開程式</summary>
```cpp=
const uint8_t LED[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
int timercnt, step, time_step;
HAL_TIM_Base_Start_IT(&htim6);
while (1) {
if (timercnt == 0) {
if (++step > 7) {
step = 0;
if (++time_step > 7) time_step = 0;
}
timercnt = (time_step + 1) * 100;
}
GPIOC->ODR = LED[step];
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (timercnt > 0) timercnt--;
}
```
</details>
## 第二章
### 兩顆按鈕搭配 LED 燈做上下數
<details>
<summary>展開程式</summary>
```cpp=
#define PC GPIOC->ODR
#define CHECK_BTN(pin) (!HAL_GPIO_ReadPin(GPIOB, pin) && flag & pin)
int value, last_flag;
while(1) {
if (CHECK_BTN(GPIO_PIN_0)) {
value = (value + 1) % 16;
} else if (CHECK_BTN(GPIO_PIN_1)) {
value = !value ? 15 : value - 1;
}
PC = value;
last_flag = GPIOB->IDR;
HAL_Delay(2);
}
```
```cpp==
#define CHECK_BTN(pin) (!HAL_GPIO_ReadPin(GPIOB, pin) && flag & pin)
const uint8_t LED[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66,
0x6d, 0x7c, 0x07, 0x7f, 0x6f};
unsigned int last_time;
int value;
char flag;
// -----
unsigned int now = HAL_GetTick();
if (last_time + 200 < now) {
if (reverse) value = value > 0 ? value - 1 : 9;
else value = (value + 1) % 9;
last_time = now;
}
if (CHECK_BTN(GPIO_PIN_0)) reverse = 1;
else if (CHECK_BTN(GPIO_PIN_1)) reverse = 0;
flag = GPIOB->IDR;
PC = ~LED[value];
HAL_Delay(20);
```
</details>
### 請設計四位數搭配三顆按鈕第一顆按鈕做上數,第二顆按鈕做下數第三顆做暫停第四顆做歸零
<details>
<summary>展開程式</summary>
```cpp=
#define PC GPIOC->ODR
#define SELECT_DISPLAY(i) ((~(1 << i) & 0xf) << 8)
#define CHECK_BTN(pin) (!HAL_GPIO_ReadPin(GPIOB, pin) && flag & pin)
char flag, value, reverse;
unsigned int time1;
const uint8_t LED[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66,
0x6d, 0x7c, 0x07, 0x7f, 0x6f};
uint32_t displays_value[4], show_index;
unsigned int time2;
void display() {
uint16_t tmp = value;
for (int i = 0; i <= 3; i++) {
displays_value[i] = LED[tmp % 10] | SELECT_DISPLAY(i);
tmp /= 10;
}
GPIOC->ODR = ~displays_value[show_index];
}
// -----
unsigned int now = HAL_GetTick();
if (time1 + 200 <= now) {
if (reverse == 1) value = value > 0 ? value - 1 : 9999;
else if (reverse == 2) value = (value + 1) % 10000;
time1 = now;
}
if (time2 + 4 <= now) {
show_index = (show_index + 1) % 4;
time2 = now;
if (CHECK_BTN(GPIO_PIN_1)) reverse = 0;
else if (CHECK_BTN(GPIO_PIN_3)) reverse = 1;
else if (CHECK_BTN(GPIO_PIN_0)) reverse = 2;
else if (CHECK_BTN(GPIO_PIN_2)) {
value = 0;
reverse = 0;
}
}
flag = GPIOB->IDR;
display();
```
</details>
## 第三章
PWM 不同頻率 與 ADC 設定
### 在頻率 1kHz 下
<details>
<summary>展開程式</summary>
```cpp=
#define SELECT_DISPLAY(i) ((~(1 << i) & 0xf) << 8)
int adc_value;
const uint8_t LED[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66,
0x6d, 0x7c, 0x07, 0x7f, 0x6f};
int LIGHT_MAP[4] = {0, 15, 50, 100};
int index;
unsigned int time;
void read_adc() {
HAL_ADC_Start(&hadc);
HAL_ADC_PollForConversion(&hadc, 1);
HAL_ADC_Stop(&hadc);
}
while(true) {
read_adc();
adc1_value = HAL_ADC_GetValue(&hadc) * 100 / 1023;
TIM2->CCR1 = LIGHT_MAP[(int) (adc1_value / 25)];
unsigned int now = HAL_GetTick();
if (time + 4 <= now) {
index = (index + 1) % 3;
time = now;
}
int value = 1;
for (int i = 0; i < index; i++) value *= 10;
int tmp = adc1_value / value;
GPIOC->ODR = ~(LED[tmp % 10] | SELECT_DISPLAY(index));
}
```
</details>
### 四位數7段顯示器
<details>
<summary>展開程式</summary>
```cpp=
#define SELECT_DISPLAY(i) ((~(1 << i) & 0xf) << 8)
const uint8_t LED[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66,
0x6d, 0x7c, 0x07, 0x7f, 0x6f};
unsigned int time;
int show_value, show_index;
while(true) {
show_value = 255;
int tmp = show_value;
for (int i = 0; i < 4; i++) {
P2 = LED[tmp % 10];
delay(3);
P2 = 0xff;
tmp /= 10;
}
}
```
```cpp=
#define SELECT_DISPLAY(i) ((~(1 << i) & 0xf) << 8)
const uint8_t LED[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66,
0x6d, 0x7c, 0x07, 0x7f, 0x6f};
unsigned int time;
int show_value, show_index;
while(true) {
show_value = 255;
unsigned int now_time = HAL_GetTick();
if (time + 4 <= now_time) {
show_index = (show_index + 1) % 4;
time = now_time;
}
int value = 1;
for (int i = 0; i < show_index; i++) value *= 10;
int tmp = show_value / value;
GPIOC->ODR = ~(LED[tmp % 10] | SELECT_DISPLAY(show_index));
}
```
```cpp=
#define SELECT_DISPLAY(i) ((~(1 << (i)) & 0xf) << 8)
#define CHECK_BTN(pin) (!HAL_GPIO_ReadPin(GPIOB, pin) && btn_flag & pin)
const uint8_t LED[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66,
0x6d, 0x7c, 0x07, 0x7f, 0x6f};
const uint16_t TONE_TAB[] = {0, 1912, 1704, 1518, 1432, 1276, 1136, 1012};
unsigned int time;
int show_value, show_index, tone_index;
char btn_flag;
void tone(int index) {
TIM2->ARR = TONE_TAB[index];
TIM2->CCR1 = TONE_TAB[index] / 2;
}
while (1) {
unsigned int now_time = HAL_GetTick();
if (time + 4 <= now_time) {
show_index = (show_index + 1) % 4;
time = now_time;
if (CHECK_BTN(GPIO_PIN_0)) {
tone_index = (tone_index + 1) % 8;
} else if (CHECK_BTN(GPIO_PIN_1) && tone_index > 0) {
tone_index--;
} else if (CHECK_BTN(GPIO_PIN_2)) {
tone_index = 0;
}
btn_flag = GPIOB->IDR;
}
// if (GPIOB->IDR)
// if (time1 + 1000 <= now_time) {
// tone_index = (tone_index + 1) % 8;
// time1 = now_time;
// }
tone(tone_index);
show_value = TONE_TAB[tone_index] / 2;
int value = 1;
for (int i = 0; i < show_index; i++) value *= 10;
int tmp = show_value / value;
GPIOC->ODR = (LED[tmp % 10] | SELECT_DISPLAY(show_index));
}
```
</details>
## Other
### UART
<details>
<summary>展開程式</summary>
```cpp=
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define UART_TX_BUFFER_SIZE 256
void UART_Transmit(const char *format, ...) {
char buffer[UART_TX_BUFFER_SIZE];
va_list args;
va_start(args, format);
int len = vsnprintf(buffer, UART_TX_BUFFER_SIZE, format, args);
va_end(args);
if (len < 0) return;
else if (len >= UART_TX_BUFFER_SIZE) {
char *dyn_buffer = (char *)malloc(len + 1);
if (dyn_buffer == NULL) return;
va_start(args, format);
vsnprintf(dyn_buffer, len + 1, format, args);
va_end(args);
HAL_UART_Transmit(&huart2, (uint8_t *)dyn_buffer, len, 200);
free(dyn_buffer);
} else {
HAL_UART_Transmit(&huart2, (uint8_t *)buffer, len, 200);
}
}
```
</details>
### Utils
<details>
<summary>展開程式</summary>
```c=
#ifndef __MK_LIB_H__
#define __MK_LIB_H__
#include "stm32l0xx_hal.h"
#ifdef __cplusplus
#include <algorithm>
using std::max;
using std::min;
#else /* __cplusplus */
#include <stdlib.h>
#ifndef abs
#define abs(x) ((x) > 0 ? (x) : -(x))
#endif /* abs */
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif /* min */
#ifndef max
#define max(a, b) ((a) > (b) ? (a) : (b))
#endif /* max */
#endif /* __cplusplus */
void delayMicroseconds(uint32_t us);
uint32_t micros(void);
inline uint32_t millis(void) {
return HAL_GetTick();
}
uint32_t pulseIn(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, uint32_t state,
uint32_t timeout);
#endif /* __MK_LIB_H__ */
```
```cpp=
void delayMicroseconds(uint32_t us) {
if (us == 0) return;
const uint32_t start = SysTick->VAL;
const uint32_t tickPerMs = SysTick->LOAD + 1;
const uint32_t ticks = ((us - 1) * tickPerMs) / 1e3;
while (start - SysTick->VAL < ticks);
}
uint32_t micros(void) {
uint32_t m0 = HAL_GetTick();
__IO uint32_t u0 = SysTick->VAL;
uint32_t m1 = HAL_GetTick();
__IO uint32_t u1 = SysTick->VAL;
const uint32_t tickPerMs = SysTick->LOAD + 1;
return m1 != m0 ? m1 * 1e3 + ((tickPerMs - u1) * 1e3) / tickPerMs
: m0 * 1e3 + ((tickPerMs - u0) * 1e3) / tickPerMs;
}
uint32_t pulseIn(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, uint32_t state,
uint32_t timeout) {
uint32_t startMicros = micros();
uint16_t stateMask = state ? GPIO_Pin : 0;
// wait for any previous pulse to end
while ((GPIOx->IDR & GPIO_Pin) == stateMask) {
if (micros() - startMicros > timeout) {
return 0;
}
}
// wait for the pulse to start
while ((GPIOx->IDR & GPIO_Pin) != stateMask) {
if (micros() - startMicros > timeout) {
return 0;
}
}
uint32_t start = micros();
// wait for the pulse to stop
while ((GPIOx->IDR & GPIO_Pin) == stateMask) {
if (micros() - startMicros > timeout) {
return 0;
}
}
return micros() - start;
}
```
</details>
# 89S52
## 四位數七段顯示器
<details>
<summary>展開程式</summary>
```cpp==
#include <regx51.h>
const unsigned char LED[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66,
0x6d, 0x7c, 0x07, 0x7f, 0x6f};
unsigned int show_value;
unsigned char show_index, j;
void delay(unsigned int ms);
void display(void);
void main() {
for (show_value = 0; show_value < 10000; show_value++) {
for (j = 0; j < 20; j++) {
for (show_index = 0; show_index < 4; show_index++) {
display();
delay(3);
P2 = 0xff;
}
}
}
}
void delay(unsigned int ms) {
unsigned int j;
unsigned char k;
for(j=0; j < ms; j++)
for(k = 0; k < 120; k++);
}
void display() {
unsigned char i;
unsigned int tmp = show_value;
for (i = 0; i < show_index; i++) tmp /= 10;
P2 = ~LED[tmp % 10];
P3 = ~(1 << show_index);
}
```
</details>
---
<!-- {%hackmd Wd1xvc_AQuSzWZPcQXSn3Q %} -->
<!--
#define CHECK_BTN(pin) (!HAL_GPIO_ReadPin(GPIOB, pin) && last_flag & pin)
uint8_t music_index, play_index, has_next_buf;
uint32_t last_flag, last_time;
#define TONE(s) (s)
const uint16_t TONE_TABLE[] = {0, 1912, 1704, 1518, 1432, 1276, 1136, 1012};
const uint16_t MUSIC_INDEX[] = {0, 52};
const uint8_t MUSIC_SIZE = sizeof(MUSIC_INDEX) / sizeof(uint16_t);
const uint16_t MUSICS[] = {
/* music-1 */
TONE(1), 4, TONE(1), 4, TONE(2), 8, TONE(1), 8, TONE(4), 8, TONE(3), 16,
TONE(1), 4, TONE(1), 4, TONE(2), 8, TONE(1), 8, TONE(5), 8, TONE(4), 16,
TONE(1), 4, TONE(1), 4, TONE(8), 8, TONE(6), 8, TONE(4), 8, TONE(3), 8,
TONE(2), 8, TONE(11), 4, TONE(11), 4, TONE(6), 8, TONE(4), 8, TONE(5), 8,
TONE(4), 16, 100, 100,
/* music-2 */
TONE(1), 4, TONE(1), 4, TONE(2), 8, TONE(1), 8, TONE(4), 8, 100, 100,
// END
};
void tone(int index) {
TIM2->ARR = TONE_TABLE[index];
TIM2->CCR1 = TONE_TABLE[index] / 2;
}
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
if (last_time > HAL_GetTick()) {
HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
HAL_Delay(5);
play_index += 2;
if (MUSICS[play_index] == 100) {
// reset
play_index = MUSIC_INDEX[music_index];
}
has_next_buf = 0;
} else if (!has_next_buf) {
has_next_buf = 1;
tone(MUSICS[play_index]);
char buf[25];
sprintf(buf, "tone: %03d", MUSICS[play_index]);
UART_SendString((uint8_t *)buf);
sprintf(buf, "; delay: %02d\r\n", MUSICS[play_index + 1]);
UART_SendString((uint8_t *)buf);
last_time = HAL_GetTick() + MUSICS[play_index + 1] * 110;
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}
if (CHECK_BTN(GPIO_PIN_0)) { // next button
music_index = (music_index + 1) % MUSIC_SIZE;
play_index = MUSIC_INDEX[music_index];
} else if (CHECK_BTN(GPIO_PIN_1)) { // prev button
music_index = !music_index ? MUSIC_SIZE : MUSIC_SIZE - 1;
play_index = MUSIC_INDEX[music_index];
}
last_flag = GPIOB->IDR;
HAL_TIM_PWM_Start(&htim21, TIM_CHANNEL_2);
HAL_TIM_Base_Start_IT(&htim6);
Initialize_LCD(hi2c1);
clear_LCD();
int status = 0;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
char str[255];
sprintf(str, "Distance : %03d", distance > 99 ? 99 : distance);
writes(0x80, str);
if (status == 7) {
sprintf(str, "NO : 11 %s", "Safe");
} else if (status >= 2){
sprintf(str, "NO : 11 %s", "Stop");
} else {
sprintf(str, "NO : 11 %s", " ");
}
writes(0xC0, str);
if (distance < 30) {
if (!timecent2) {
if (distance < 10) {
timecent2 = 400;
} else if (distance < 20) {
timecent2 = 800;
} else {
timecent2 = 1200;
}
status = (status + 1) % 6;
}
if (status % 2) {
TIM21->ARR = 1912;
TIM21->CCR2 = 956;
} else {
TIM21->ARR = 0;
TIM21->CCR2 = 0;
}
} else {
TIM21->ARR = 0;
TIM21->CCR2 = 0;
status = 7;
}
if (timecent == 0) {
timecent = 800;
trigger();
while (!PB2_R);
__HAL_TIM_SET_COUNTER(&htim2, 0);
HAL_TIM_Base_Start(&htim2);
while (PB2_R);
HAL_TIM_Base_Stop(&htim2);
distance = __HAL_TIM_GetCounter(&htim2) / 58;
distance = distance > 99 ? 99 : distance;
}
-->
<!--
#include <regx51.h>
unsigned char mode, old_mode, old, tmp2, tmp3;
unsigned int tmp1;
void delay(unsigned int ms);
void main() {
while (1) {
// unsigned char tmp = !P3_2;
// if (tmp && tmp != old) {
// mode = (mode + 1) % 6;
// }
// old = tmp;
mode = (~P0 & 0x07) % 6;
if (mode != old_mode) {
tmp1 = tmp2 = 0x00;
old_mode = mode;
tmp3 = 1;
}
if (!tmp1) {
switch (mode) {
case 0: {
tmp2 = 0x00;
} break;
case 1: {
tmp2 = 0xff;
} break;
case 2: {
tmp2 = tmp3 ? 0xff : 0x00;
tmp3 = !tmp3;
} break;
case 3: {
tmp2 <<= 1;
if (!tmp2) tmp2 = 0x01;
} break;
case 4: {
tmp2 >>= 1;
if (!tmp2) tmp2 = 0x80;
} break;
case 5: {
tmp2 = tmp3 ? tmp2 << 1 : tmp2 >> 1;
if (!tmp2) {
tmp3 = !tmp3;
tmp2 = tmp3 ? 0x02 : 0x40;
}
} break;
}
}
P1 = ~tmp2;
if (tmp1 > 0) tmp1--;
else tmp1 = 500;
delay(1);
}
}
void delay(unsigned int ms) {
unsigned int j;
unsigned char k;
for(j=0; j < ms; j++)
for(k = 0; k < 120; k++);
}
-->