查看: 40|回复: 0

[技术] 【赚周年币】技术贴Week1-Day5——【 Atmel G53】PIO学习二

[复制链接]

56

主题

1

好友

1819

积分

进士

Rank: 5Rank: 5

  • TA的每日心情
    奋斗
    昨天 19:15
  • 签到天数: 572 天

    [LV.9]以坛为家II

    爱板会员勋章 活跃会员勋章 发帖机器勋章 在线达人勋章

    发表于 2017-1-2 16:39:21 |显示全部楼层
    本帖最后由 wambob 于 2017-1-2 18:43 编辑

           ASF库里有3个IOPORT例程,为了进一步学习IOPORT,打开了第二个例子,细看之下,发现控制管脚的函数不相同。第二个例子里直接控制端口的一个管脚。
    比如:
    例一中的函数
    1. ioport_set_port_dir(EXAMPLE_LED_PORT, EXAMPLE_LED_MASK, //设置LED端口、位、方向为输出
    2. IOPORT_DIR_OUTPUT);
    复制代码
    例二中的函数
    1. ioport_set_pin_dir(EXAMPLE_LED, IOPORT_DIR_OUTPUT);
    复制代码
    两个函数都可以控制端口的一个管脚,区别是,例一中的函数不仅可以控制一个管脚,还可以控制一组。PIO在数据手册中的说明是并行I/O口。相关寄存器是32位的:
    3.JPG

    实际上引出的只有一部分:
    1.JPG

    那么第三个例程给的是什么知识呢,打开例程3,发现使用的函数和例程二一样,只不过在函数参数中使用了函数返回值作为实参。
    1. ioport_set_pin_level(EXAMPLE_LED,
    2.                                 ioport_get_pin_level(EXAMPLE_BUTTON));
    复制代码
    我想驱动16位的LCD,结果发现一个问题。回顾例一中的控制端口的函数:
    1. /* Set LED IOPORTs high */
    2.         ioport_set_port_level(EXAMPLE_LED_PORT, EXAMPLE_LED_MASK,
    3.                         IOPORT_PIN_LEVEL_HIGH);
    复制代码
    这个真能控制LED脚输出高电平吗?
    为什么这么说?
    先看看这个函数的3个参数:
                                  1.#define EXAMPLE_LED_PORT (0)          且#define IOPORT_PIOA     0            这个表示端口A,没问题
                                  2.#define EXAMPLE_LED_MASK ((1 << 16))
    这句表示PA端口的第17个管脚,PA16 也没问题。
                                3.这个参数是个枚举常量
    1. enum ioport_value {
    2.         IOPORT_PIN_LEVEL_LOW,  /*!< IOPORT pin value low */
    3.         IOPORT_PIN_LEVEL_HIGH, /*!< IOPORT pin value high */
    4. };
    复制代码
    看上去似乎没有问题。先不讲真确答案。先验证下:去掉原先的端口翻转函数
    1. ioport_toggle_port_level(EXAMPLE_LED_PORT, EXAMPLE_LED_MASK);       //翻转LED端口
    复制代码
    while循环里换成如下语句测试
    1. ioport_set_port_level(EXAMPLE_LED_PORT, EXAMPLE_LED_MASK,          //设置LED端口、位、电平高
    2.                         IOPORT_PIN_LEVEL_LOW);
    3. delay_ms(500);
    4. ioport_set_port_level(EXAMPLE_LED_PORT, EXAMPLE_LED_MASK,          //设置LED端口、位、电平高
    5.                         IOPORT_PIN_LEVEL_HIGH);
    6. delay_ms(500);
    复制代码
    目的是使端口A的PA16 输出占空比50%,周期1s的方波驱动LED闪烁,结果编译后下载到板上,LED只亮,并不闪烁。这就有问题了?
           来追根逐源下此函数原型:
    1. static inline void ioport_set_port_level(ioport_port_t port,
    2.                 ioport_port_mask_t mask, ioport_port_mask_t level)
    3. {
    4.         arch_ioport_set_port_level(port, mask, level);
    5. }
    复制代码
    调用了一个封装的函数,继续:
    1. __always_inline static void arch_ioport_set_port_level(ioport_port_t port,
    2.                 ioport_port_mask_t mask, ioport_port_mask_t level)
    3. {
    4.         Pio *base = arch_ioport_port_to_base(port);

    5.         base->PIO_SODR = mask & level;
    6.         base->PIO_CODR = mask & ~level;
    7. }
    复制代码
    端口解析后赋给了一个Pio类型的指针。
    下面这两条语句当level的值为1时无论如何也不能把第一位除外的mask位置1,当level值为0时也不能把第一位除外的mask位置0;
    而主程序中传过的参数是枚举常量0和1。
    这个函数如果要正常工作,置1时两个参数mask和level相同。清0时相反。
    修改主程序whilex循环验证代码:
    1. /* Toggle LED IOPORTs with half a second interval */
    2.                 ioport_set_port_level(EXAMPLE_LED_PORT, EXAMPLE_LED_MASK,
    3.                 EXAMPLE_LED_MASK);
    4.                 delay_ms(500);
    5.                 ioport_set_port_level(EXAMPLE_LED_PORT, EXAMPLE_LED_MASK,
    6.                 ~EXAMPLE_LED_MASK);
    7.                 delay_ms(500);
    复制代码
    编译后下载代码,观察板子,LED闪烁了。
                                 
    已有 2 人评分周年币 收起 理由
    EEboard爱板网 + 15 3周发帖养成记 奖励
    loveeeboard + 10

    总评分: 周年币 + 25   查看全部评分

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    关闭

    站长推荐上一条 /1 下一条

    手机版|爱板网 |网站地图  

    GMT+8, 2017-1-19 12:27 , Processed in 0.162867 second(s), 15 queries , Memcache On.

    苏公网安备 32059002001056号

    Powered by Discuz!

    回顶部