【匠芯创D133CBS】--3.按键控灯
<div class='showpostmsg'> 本帖最后由 dirty 于 2024-8-17 11:35 编辑<p> 本篇讲述按键驱动实现与消息队列发送与接收控灯。</p>
<p> </p>
<p><strong><span style="color:#0000ff;">一.硬件原理</span></strong></p>
<p> <a href="https://www.artinchip.com/knowledge/oxy_ex-1/topics/d133cbv-v1-0-d13x.html?hl=d133cbv" target="_blank">匠芯创D133CBV-QFN88-V1-2 原理图</a>可查到唤醒按键如下,使用到引脚为PD15.</p>
<div style="text-align: center;">
<div style="text-align: center;"></div>
<p> </p>
</div>
<div style="text-align: center;">图1:唤醒按键原理</div>
<p> LED引脚如前篇所述,使用PD0脚。</p>
<p> </p>
<p><strong><span style="color:#0000ff;">二.代码准备</span></strong></p>
<p>1.scons --menuconfig配置使能RT-Thread内核</p>
<div style="text-align: center;"></div>
<p>2.按键初始化,这里使用上升沿触发,即按键松开后进入key_irq_handler回调。按键、LED引脚宏定义。</p>
<pre>
<code>#define LED_PIN "PD.0"
#define KEY_PIN "PD.15"
void app_key_init(void)
{
// 1.get pin number
static u32 pin = 0;
pin = rt_pin_get(KEY_PIN);
printf("Key pin%d\n",pin);
// 2.set pin mode to Input-PullUp
rt_pin_mode(pin, PIN_MODE_INPUT_PULLUP);
// 3.attach irq handler
rt_pin_attach_irq(pin, PIN_IRQ_MODE_RISING,key_irq_handler, &pin);//PIN_IRQ_MODE_RISING_FALLING
// 4.enable pin irq
rt_pin_irq_enable(pin, PIN_IRQ_ENABLE);
rt_kprintf("%s\r\n",__func__);
}</code></pre>
<p>3.创建消息队列,数据以结构体发送与接收。编写消息队列发送函数。</p>
<pre>
<code>typedef struct
{
uint16_t msg_len;
uint8_t led_value;
}msg_control;
/* 消息队列控制块 */
static struct rt_messagequeue user_mq;
/* 消息队列中用到的放置消息的内存池 */
static rt_uint8_t msg_pool;
msg_control msg_control_t;
//消息队列发送
void app_msg_send(uint8_t *buff,uint16_t len)
{
rt_err_t ret;
ret = rt_mq_send(&user_mq,buff,len);
if (ret != RT_EOK)
{
rt_kprintf("rt_mq_send fail. ret:%d\n",ret);
}
}
void app_user_mq_init(void)
{
rt_err_t ret;
/* 初始化消息队列 */
ret = rt_mq_init(&user_mq,
"user_mq",
&msg_pool, /* 内存池指向msg_pool */
sizeof(msg_control_t), /* 每个消息的大小是 1 字节 */
sizeof(msg_pool), /* 内存池的大小是msg_pool的大小 */
RT_IPC_FLAG_FIFO); /* 如果有多个线程等待,按照先来先得到的方法分配消息 */
if (ret != RT_EOK)
{
rt_kprintf("init user message queue failed.\n");
}
}</code></pre>
<p>4.在按键中断回调实现led状态值取反,并消息队列发送</p>
<pre>
<code>static void key_irq_handler(void *args)
{
unsigned int ret;
u32 pin = *((u32 *)(args));
printf("Key INT\r\n");
msg_control_t.msg_len=sizeof(msg_control_t);
msg_control_t.led_value=!msg_control_t.led_value;
app_msg_send(&msg_control_t,sizeof(msg_control_t));
// times_enter_irq++;
// hal_gpio_get_value(GPIO_GROUP(pin), GPIO_GROUP_PIN(pin), &ret);
// printf("gpio group_%d_pin_%d read = %d\n", GPIO_GROUP(pin), GPIO_GROUP_PIN(pin), ret);
}</code></pre>
<p>5.在任务里接收消息队列,并按LED状态值控制LED</p>
<pre>
<code>void led_thread_entry(void *parameter)
{
int pin;
msg_control msg_control_p;
while(1)
{
//消息队列接收
if(rt_mq_recv(&user_mq, &msg_control_p, sizeof(msg_control_p), RT_WAITING_FOREVER)==RT_EOK)
{
rt_kprintf("Receive msg quene\r\n");
rt_kprintf("msg_len:%d,led_value:%d\r\n",msg_control_p.msg_len,msg_control_p.led_value);
pin = rt_pin_get(LED_PIN);
rt_pin_write(pin, msg_control_p.led_value);
}
}
}</code></pre>
<p> </p>
<p><strong><span style="color:#0000ff;">三.测验</span></strong></p>
<p> 编译烧录,按一下WAKEUP按键,LED灯取反一次亮/灭 如视频,串口日志如下</p>
<div style="text-align: center;"></div>
<div style="text-align: center;">图3:按键控灯日志</div>
<p> 至此,实现按键驱动及通过消息队列发送接收同步控制LED.</p>
<p> </p>
<p>e5bc0e40dc0cdb2fd2f6e50c1af8dac1<br />
</p>
</div><script> var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
(function($){
var postHeight = getTextHeight(400);
$(".showpostmsg").html($(".showpostmsg").html());
$(".showpostmsg").after(loginstr);
$(".showpostmsg").css({height:postHeight,overflow:"hidden"});
})(jQuery);
} </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>
页:
[1]