gpio模拟uart 发送

用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一次:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值