freertos上进行gpio模拟iic通信

一、第一个问题:

因为iic通信是需要微秒级延时的,而freertos上只有毫秒级的延时。于是上网查了资料,可以用systicks的计数次数来实现us级延时(与linux驱动的定时器类似),亲测可用

//初始化函数

uint32_t DWT_Dalay_Init(void)
{
    CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk;
    CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
    DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk;
    DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
    DWT->CYCCNT = 0;
    __ASM volatile ("NOP");
    __ASM volatile ("NOP");
    __ASM volatile ("NOP");

    if(DWT->CYCCNT)
    {
        return 0;
    }
    else{
        return 1;
    }
}

//延时函数,参数是n微秒
void DWT_Delay_us(volatile uint32_t nus)
{
    uint32_t clk_cycle_start = DWT->CYCCNT;  // 获得当前次数
    nus *= 72; // 72MHZ时,1us的时钟脉冲为72,1us计数72次,nus则是nus *= 72

    while((DWT->CYCCNT - clk_cycle_start < us));  // 当计数次数达到预期时,跳出循环
}

二、第二个问题:

因为freertos是通过时间片轮转来实现多任务同时执行的,而iic的通信是毫秒级延时,所以,在iic收发数据时,要求不能进行任务调度。一开始想到的是互斥锁(信号量):

SemaphoreHandle_t Mutex;

xSemaphoreTake(Mutex, portMAX_DELAY); //获得锁

xSemaphoreGive(Mutex);//解锁

但使用后发现,互斥锁的主要功能是避免多任务同时访问临界资源,而我想实现的功能是进行iic通信时,freertos停止任务调度,因此,我使用的是任务锁,亲测有效:

vTaskSuspendAll();

iic通信代码;

 if(xTaskResumeAll())
 {
      taskYIELD();
 }

详细请看:FreeRTOS 调度锁,任务锁和中断锁 - 走看看

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值