实验连接示意图

所用器材列表
硬件
- STM32F103核心板一块
- microUSB线
- STLinkban板和USB串口板
软件
- 交叉编译软件
实验步骤、操作的命令和结果
连接STM32和其他设备
写一个自己的建议bootloader,能通过串口执行两条最简单的指令:
1 | // 串口输出单个字符 void myPutc(char ch) { HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,100); } // 串口输出字符串 void myPuts(char *str) { for (int i = 0; i < strlen(str); i++) myPutc(str[i]); } // 串口读取单个字符(时限time_bound) int8_t myGetc(uint8_t *c, uint16_t time_bound) { while (time_bound) { // 时限控制 if (uart_rev.front != uart_rev.rear) { *c = *uart_rev.front; uart_rev.front++; if (uart_rev.front >= buf + BUFSIZE) // 下标控制 uart_rev.front = buf; return 0; } time_bound--; } return (int8_t) – 1; } // 串口读取字符串 int8_t myGets(uint8_t *str, uint16_t bound) { int count = 0; bound--; while (count < bound) { if (uart_rev.front != uart_rev.rear) { char ch = *uart_rev.front; uart_rev.front++; if (uart_rev.front > buf + BUFSIZE) uart_rev.front = buf; if (ch == '\r') // 处理换行 break; *str = ch; if (ch != ' ') { // 非空有效 str++; count++; } } } *str = '\0'; return count; } |
中断处理
1 | void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle) { uint8_t ret = HAL_OK; char ch = *uart_rev.rear; myPutc(ch); if (c == '\r') // 回车补’\n’ myPutc('\n'); // 移动buf指针 uart_rev.rear++; if (uart_rev.rear > buf + BUFSIZE) uart_rev.rear = buf; if (uart_rev.rear == uart_rev.front) { uart_rev.front++; if (uart_rev.front > buf + BUFSIZE) uart_rev.front = buf; } do{ }while(HAL_UART_Receive_IT(UartHandle, uart_rev.rear, 1) != HAL_OK); } void USART1_IRQHandler(void){ //调用HAL函数库自带的处理函数 HAL_UART_IRQHandler(&huart1); } |
命令处理
while (1) {
char cmd[MAXLEN];
char s2[MAXLEN];
count = 0;
myPuts("Please input your instruction: ");
count = myGets((uint8_t*)s1, MAXLEN); // 获取输入
sscanf(s1, "%s", cmd);
if (strcmp(cmd, "peek") == 0) { // “peek”命令
int addr;
int res = sscanf(s1 + PEEKLEN, “%x %s”, &addr, s2);
if (res == 1) {
sprintf(s2, "peek: %x %x\r\n, addr, *((int *)addr)");
myPuts(s2); // 输出结果
}
else myPuts("error\r\n");
}
else if (strcmp(cmd, "poke") == 0) {
int addr, data;
int res = sscanf(str + POKELEN, "%x %x %s", &addr, &data, s);
if (res == 2) {
*((int *)addr) = data; // 写入数据
sprintf(s2, "poke: %x %x\r\n", addr, *((int *)addr));
myPuts(s2);
}
else myPuts("error\r\n"); // 出错
}
else myPuts("error\r\n"); // 非peek或poke命令
}
结果与分析
poke命令执行完之后,peek对应地址能得到正确的数据,符合实验预期。