赞
踩
串口的时序就不再多讲了,主要是分享一个比自己写的IO模拟串口的实例
申明:
这个波特率为115200
分频系数为8
自动重载值为68
约等于8.7微秒
使用其他波特率或者IO口,只需要修改.h文件中的对应参数即可
头文件
- #ifndef IO_UART_H
- #define IO_UART_H
-
- #include "tim.h"
-
- enum
- {
- N_CMD, //空闲
- W_CMD, //写
- R_CMD, //读
- F_CMD, //完成
- };
- enum
- {
- UNWAIT,
- WAITING,
- };
-
-
- #define U_TIM TIM4 //UART内部定时器
- #define TX_GPIO_PIN GPIO_PIN_15 //UART对应的TX引脚
- #define RX_GPIO_PIN GPIO_PIN_14 //UART对应的RX引脚
- #define TX_PIN 14 //UART对应的TX引脚编号
- #define RX_PIN 15 //UART对应的RX引脚编号
- #define TX_GPIO GPIOB //UART对应的TX端口
- #define RX_GPIO GPIOB //UART对应的RX端口
-
- #define MAX_WAIT 0x5 //最大等待时间
- #define T_RELOAD 68 //发送一个字节所需的时间
- #define T_FIRST 0x33 //延时到第一位的时间
-
- #define MAX_BUFSIZE 3000 //收发最大字符数量
-
-
- /************************************
- function : 定时器中断回调函数
- ************************************/
- void TIM_UART_Callback(TIM_HandleTypeDef *htim);
- /************************************
- function : 外部中断回调函数
- ************************************/
- void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
- /************************************
- function : 发送一个字节
- input : uint8_t send_data //要发送的字节
- return : void
- ************************************/
- void SEND_BYTE(uint8_t send_data);
- /************************************
- function : 发送一个字符串
- input : uint8_t *send_data //要发送的字符串
- return : void
- ************************************/
- void SEND_STRING(uint8_t *send_data);
- /************************************
- function : 等待读取一个字符串
- input : uint8_t *read_data //接收目标字符串
- return : void
- ************************************/
- void READ_STRING(uint8_t *read_data);
- /************************************
- function : 清空一个字符串
- input : uint8_t *string //要清楚的字符串 size_t str_len //清除字符串的长度
- return : void
- ************************************/
- void ZERO_STRING(uint8_t *string,size_t str_len);
- /************************************
- function : UART初始化
- input : void
- return : void
- ************************************/
- void UART_INIT(void);
- #endif
-
-
-
.c文件
- #include "io_uart.h"
-
- volatile uint8_t uart_flag = N_CMD;
- uint8_t cnt_bit = 0;
- uint8_t uart_data = 0;
- uint8_t wait_flag = UNWAIT;
- uint8_t **buf = NULL;
- uint32_t i = 0;
-
- /************************************
- function : 拉高TXD
- ************************************/
- static void SET_TXD(void)
- {
- TX_GPIO->BSRR = TX_GPIO_PIN;
- }
- /************************************
- function : 拉低TXD
- ************************************/
- static void RESET_TXD(void)
- {
- TX_GPIO->BSRR = (uint32_t)TX_GPIO_PIN << 16u;
- }
- /************************************
- function : 读取RXD电平
- ************************************/
- static uint8_t READ_RXD(void)
- {
- return ((RX_GPIO->IDR & RX_GPIO_PIN) >> TX_PIN);
- }
- /************************************
- function : 定时器中断回调函数
- ************************************/
- void TIM_UART_Callback(TIM_HandleTypeDef *htim)
- {
- //写一个字节
- if(uart_flag == W_CMD)
- {
- if(cnt_bit == 0)
- {
- //拉低TXD
- RESET_TXD();
- }
- else if(cnt_bit > 0 && cnt_bit < 9)
- {
- if(uart_data & (0x01 << (cnt_bit - 1)))
- {
- //输出高电平
- SET_TXD();
- }
- else
- {
- //输出低电平
- RESET_TXD();
- }
- }
- else
- {
- //拉高TXD
- SET_TXD();
- cnt_bit = 0;
- uart_flag = N_CMD;
- uart_data = 0;
- //关闭定时器中断
- U_TIM->CR1 &= ~(TIM_CR1_CEN);
- return;
- }
- cnt_bit++;
- }
- //读一个字节
- else if(uart_flag == R_CMD)
- {
- if(cnt_bit == 0)
- {
- //设置定时器定时时间
- U_TIM->ARR = T_RELOAD;
- }
- else if(cnt_bit == 8)
- {
- cnt_bit = 0;
- /****new****/
- //设置定时器定时时间
- U_TIM->CNT = 0x00;
- U_TIM->ARR = T_RELOAD*MAX_WAIT;
- (*buf)[i] = uart_data;
- i++;
- uart_data = 0;
- wait_flag = WAITING;
- cnt_bit = 0;
- //打开外部中断
- EXTI->PR = (RX_GPIO_PIN);
- EXTI->IMR |= (0x1 << TX_PIN);
- /****new****/
- return;
- }
- uart_data |= (READ_RXD() << cnt_bit);
- cnt_bit++;
- //判断是否读取完成
- if(wait_flag == WAITING)
- {
- //读取完成
- uart_flag = F_CMD;
- wait_flag = UNWAIT;
- //关闭定时器中断
- U_TIM->CR1 &= ~(TIM_CR1_CEN);
- //关闭外部中断
- EXTI->IMR &= ~(0x1 << TX_PIN);
- return;
- }
- }
- }
- /************************************
- function : 外部中断回调函数
- ************************************/
- void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
- {
- switch(GPIO_Pin)
- {
- case RX_GPIO_PIN:
- EXTI->PR = (RX_GPIO_PIN);
- if(uart_flag != R_CMD)
- return;
- else
- {
- wait_flag = UNWAIT;
- //关闭定时器中断
- U_TIM->CR1 &= ~(TIM_CR1_CEN);
- //设置定时器定时时间
- U_TIM->CNT = 0x00;
- U_TIM->ARR = T_FIRST;
- //打开定时器中断
- U_TIM->SR = ~(TIM_IT_UPDATE);
- U_TIM->CR1 |= (TIM_CR1_CEN);
- //关闭外部中断
- EXTI->IMR &= ~(0x1 << TX_PIN);
- EXTI->PR = (RX_GPIO_PIN);
- }
- break;
- default:
- break;
- }
- }
- /************************************
- function : 发送一个字节
- input : uint8_t send_data //要发送的字节
- return : void
- ************************************/
- void SEND_BYTE(uint8_t send_data)
- {
- while(uart_flag != N_CMD);
- uart_flag = W_CMD;
- cnt_bit = 0;
- uart_data = send_data;
- //打开定时器中断
- U_TIM->SR = ~(TIM_IT_UPDATE);
- U_TIM->CR1 |= (TIM_CR1_CEN);
- while(uart_flag != N_CMD);
- }
- /************************************
- function : 发送一个字符串
- input : uint8_t *send_data //要发送的字符串
- return : void
- ************************************/
- void SEND_STRING(uint8_t *send_data)
- {
- uint32_t j = 0;
- for(j = 0; (send_data[j] != 0 || send_data[j+1] != 0) && i < MAX_BUFSIZE-1; j++)
- {
- SEND_BYTE(send_data[j]);
- }
- }
- /************************************
- function : 等待读取一个字符串
- input : uint8_t *read_data //接收目标字符串
- return : void
- ************************************/
- void READ_STRING(uint8_t *read_data)
- {
- while(uart_flag != N_CMD);
- i = 0;
- buf = &read_data;
- cnt_bit = 0;
- uart_flag = R_CMD;
- //打开外部中断
- EXTI->PR = (RX_GPIO_PIN);
- EXTI->IMR |= (0x1 << TX_PIN);
- while(uart_flag != F_CMD);
- //read_data[255] read_data[254] read_data[256] read_data[258] read_data[0] read_data[1]
- buf = NULL;
- uart_data = 0;
- cnt_bit = 0;
- uart_flag = N_CMD;
- }
- /************************************
- function : 清空一个字符串
- input : uint8_t *string //要清楚的字符串 size_t str_len //清除字符串的长度
- return : void
- ************************************/
- void ZERO_STRING(uint8_t *string,size_t str_len)
- {
- int i = 0;
- for(i = 0; i < str_len; i++)
- {
- string[i] = 0;
- }
- return;
- }
- /************************************
- function : UART初始化
- input : void
- return : void
- ************************************/
- void UART_INIT(void)
- {
- //清空定时器中断标志位
- U_TIM->SR = ~(TIM_IT_UPDATE);
- //关闭定时器中断
- U_TIM->DIER |= (TIM_IT_UPDATE);
- U_TIM->CR1 &= ~(TIM_CR1_CEN);
- //关闭外部中断
- EXTI->IMR &= ~(0x1 << TX_PIN);
- //清空外部中断标志位
- EXTI->PR = (RX_GPIO_PIN);
- }
- //
-
/************************************
function : 定时器中断回调函数
************************************/
void TIM_UART_Callback(TIM_HandleTypeDef *htim);这个定时器回调函数写在对应的HAL的回调函数中,
/************************************
function : 外部中断回调函数
************************************/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);如果使用了其他的外部中断,可以像定时器中断那样改一个名字后放入对应的HAL库的外部中断函数中
如果程序出现了什么问题,欢迎和我交流
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。