用GPIO模拟UART输出一个字节,波特率9600,所以周期约为104us。
这就需要用的精确的usdelay延时函数;延时函数可以用Cortex-M内核中的DWT计数器。
另外还需要将GPIO配置成output模式;
延时函数实现如下:
delay.h
//延时实现
#define DWT_CR *(__IO uint32_t *)0xE0001000
#define DWT_CYCCNT *(__IO uint32_t *)0xE0001004
#define DEM_CR *(__IO uint32_t *)0xE000EDFC
#define DBGMCU_CR *(__IO uint32_t *)0xE0042004
#define DEM_CR_TRCENA (1 << 24)
#define DWT_CR_CYCCNTENA (1 << 0)
extern uint32_t measure_time_pre,measure_time;
#define TIME_MEASURE_START measure_time_pre = (uint32_t)DWT_CYCCNT
#define TIME_MEASURE_STOP measure_time = ((uint32_t)DWT_CYCCNT > measure_time_pre)?((uint32_t)DWT_CYCCNT - measure_time_pre):((uint32_t)DWT_CYCCNT + 0xFFFFFFFF - measure_time_pre)
delay.c
uint32_t measure_time_pre=0,measure_time=0;
void delay_init(void) //ԵʼۯDWTì{ԃDWTѐdelay
{
DEM_CR |= (uint32_t)DEM_CR_TRCENA; /* Enable Cortex-M3's DWT CYCCNT reg. */
DWT_CYCCNT = (uint32_t)0u;
DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
}
void delay_deinit(void) //ȥԵʼۯDWTì{ԃDWTѐdelay
{
DEM_CR &= ~(uint32_t)DEM_CR_TRCENA; /* Enable Cortex-M3's DWT CYCCNT reg. */
DWT_CYCCNT = (uint32_t)0u;
DWT_CR &= ~(uint32_t)DWT_CR_CYCCNTENA;
}
//void delay_ms(uint32_t nms)
//{
// delay_us(nms*1000);
//}
void Delay_us(uint32_t nus)
{
uint32_t stime,etime;
stime = (uint32_t)DWT_CYCCNT;
etime = (uint32_t)DWT_CYCCNT + (80*nus);//݆̣կս̹ѨғʱʱݤքDWT_CYCCNT݆˽ֵìӬڽ32bit̹Ŝҭկքخճֵ2ք32Վ-1ˇؔ֯Ɇܘ֪Ǻλ
if(etime > stime)//ƐˇرࠧԽخճֵҟާ
{
while((uint32_t)DWT_CYCCNT < etime)//ֈսսկʱݤ
{
// IWDG_ReloadCounter();//ߴąٷȥ£
}
}
else
{
while((uint32_t)DWT_CYCCNT > etime)//ֈսࠧԲ32bitքخճֵì2ք32Վ-1
{
// IWDG_ReloadCounter();//ߴąٷȥ£
}
while((uint32_t)DWT_CYCCNT < etime)//ֈսսկʱݤ
{
// IWDG_ReloadCounter();//ߴąٷȥ£
}
}
}
void Delay(uint32_t count)
{
while(count--);
}
实现gpio模拟uart发送的函数如下:
void n_gpio_uart_send_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void sendByte(uint8_t val)
{
// HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
Delay_us(104);
for (int i = 0; i < 8; i++)
{
if (val & 0x01)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
}
Delay_us(104);
val >>= 1;
}
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
Delay_us(104);
}
mian.c中调用初始化,并用sendByte发送数据,串口即可收到发送的数据:
mian.c
int main(void)
{
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_CAN1_Init();
MX_CRC_Init();
MX_I2C1_Init();
MX_RTC_Init();
MX_SPI2_Init();
MX_TIM6_Init();
MX_TIM7_Init();
MX_USART1_UART_Init();
delay_init();
n_gpio_uart_send_init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
char *str="uart3-dma send data test.\r\n";
for(int i=0;i<strlen(str);i++)
{
sendByte(str[i]);
}
while (1)
{
delay_ms(1000);
for(int i=0;i<strlen(str);i++)
{
sendByte(str[i]);
}
}
}
串口接收数据:1s一次: