由于项目需要开始接触Microchip(原Atmel)家的这款MCU,使用工具是SAM E70 X PLAINED ULTRA开发板。本系列用于记录从0开始一步步熟悉这款MCU的开发过程。开发板外设资源丰富,之前一直是使用HAL库开发ST/GD系列的MCU,Microchip的开发风格与前两者存在一定差异,借此机会巩固一下基础知识。

上篇学习了GPIO、UART的简单使用,本章讲学习使用IIC、SPI、PWM等常见外设。

开发板用户手册

IIC主机

IIC协议简要回顾

在这里插入图片描述

起始信号、结束信号等概念不再展开介绍。

IIC写

开发板上自带一块EEPROM(AT24),设备地址0x57。在图形界面中使能IIC(TWIHS)
在这里插入图片描述

配置IIC,主机模式,400kHz
在这里插入图片描述

配置完成后,修改main函数,代码如下:

uint8_t hello_str[] = "hello from the SAM E70 X PLAINED ultra";
int main ( void )
{
    /* Initialize all modules */
    SYS_Initialize ( NULL );
    printf("%s at %s %s\r\n", hello_str, __DATE__, __TIME__);
    TWIHS0_Write(0x57, hello_str, sizeof(hello_str));

    while ( true )
    {
        LED3_Toggle();
        SYSTICK_DelayMs(500);
        /* Maintain state machines of all polled MPLAB Harmony modules. */
        SYS_Tasks ( );
    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}

使用逻辑分析仪抓取波形,效果如下:
在这里插入图片描述

IIC从机

开发板具有三个IIC外设,选择IIC2作为从机(三个IIC都可以根据需要设置为主机或从机),图形设置如下:
在这里插入图片描述

这里我们设置从机地址为0x54。同时使用一块STM32作为IIC主机与开发板通信,STM32的配置这里不做介绍。
与主机不同的是,从机生成的库文件只实现了中断代码,并未实现具体的回调函数需要手动注册。
初始化代码如下:

void TWIHS2_Initialize( void )
{
    /* Reset the TWIHS Module */
    TWIHS2_REGS->TWIHS_CR = TWIHS_CR_SWRST_Msk;

    /* Disable the TWIHS Master/Slave Mode */
    TWIHS2_REGS->TWIHS_CR = TWIHS_CR_MSDIS_Msk | TWIHS_CR_SVDIS_Msk;

    /* Configure slave address */
    TWIHS2_REGS->TWIHS_SMR = TWIHS_SMR_SADR(0x54);

    /* Clear the Transmit Holding Register and set TXRDY, TXCOMP flags */
    TWIHS2_REGS->TWIHS_CR = TWIHS_CR_THRCLR_Msk;

    /* Initialize the TWIHS PLIB Object */
    /* Enable interrupt for Slave Access and End of Slave Access */
    TWIHS2_REGS->TWIHS_IER = TWIHS_IER_SVACC_Msk | TWIHS_IER_EOSACC_Msk;

    twihs2Obj.callback = NULL;
    twihs2Obj.isBusy = false;
    twihs2Obj.isFirstTxPending = false;
    twihs2Obj.isAddrMatchEventNotified = false;

    /* Enable Slave Mode */
    TWIHS2_REGS->TWIHS_CR = TWIHS_CR_SVEN_Msk;

    TWIHS2_CallbackRegister(TWIHS2_SlaveCallback, 0);//手动调用,其中TWIHS2_SlaveCallback需自行实现
}

void TWIHS2_CallbackRegister(TWIHS_SLAVE_CALLBACK callback, uintptr_t contextHandle)
{
    twihs2Obj.callback = callback;

    twihs2Obj.context  = contextHandle;
}

plib_twihs_slave_common.h中可以看到需要实现以下几种事件回调。

typedef enum
{
    TWIHS_SLAVE_TRANSFER_EVENT_NONE = 0,

    /* Address match event */
    TWIHS_SLAVE_TRANSFER_EVENT_ADDR_MATCH,

    /* Data sent by I2C Master is available */
    TWIHS_SLAVE_TRANSFER_EVENT_RX_READY,

    /* I2C slave can respond to data read request from I2C Master */
    TWIHS_SLAVE_TRANSFER_EVENT_TX_READY,

    /* I2C stop condition received or start condtion with other slave address detected */
    TWIHS_SLAVE_TRANSFER_EVENT_TRANSMISSION_COMPLETE,

}TWIHS_SLAVE_TRANSFER_EVENT;

typedef bool (*TWIHS_SLAVE_CALLBACK) ( TWIHS_SLAVE_TRANSFER_EVENT event, uintptr_t contextHandle );

从机回调函数实现

手动实现的回调函数如下,只是简单实现接收和发送功能:

bool TWIHS2_SlaveCallback(TWIHS_SLAVE_TRANSFER_EVENT event, uintptr_t context)
{
    (void)context;

    switch (event)
    {
        case TWIHS_SLAVE_TRANSFER_EVENT_ADDR_MATCH:
            reg_idx          = 0;
            break;

        case TWIHS_SLAVE_TRANSFER_EVENT_RX_READY:
        {
            uint8_t data = TWIHS2_ReadByte();

            read_buffer[reg_idx] = data;
            if (++reg_idx >= I2C_SLAVE_BUFFER_SIZE)
                reg_idx = 0;
            break;
        }

        case TWIHS_SLAVE_TRANSFER_EVENT_TX_READY:
             TWIHS2_WriteByte(read_buffer[reg_idx]);
             if (++reg_idx >= I2C_SLAVE_BUFFER_SIZE)
                reg_idx = 0;
            break;

        case TWIHS_SLAVE_TRANSFER_EVENT_TRANSMISSION_COMPLETE:
            break;

        default:
            break;
    }

    return true;
}

在STM32中对从机先写后读,核心代码如下:

uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x05};
uint8_t rd_data[5];
HAL_I2C_Master_Transmit(&hi2c1, 0x54 << 1, data, 5, 1000);
HAL_I2C_Master_Receive(&hi2c1, 0x54 << 1, rd_data, 5, 1000);

STM32调试可以抓取到读到的数据如下:
在这里插入图片描述

同时可以使用逻辑分析仪抓取数据,效果如下:
在这里插入图片描述

SPI

SPI协议简要回顾

在这里插入图片描述

由CPOL和CPHA组成四种模式:
在这里插入图片描述
在这里插入图片描述
使用图形界面使能SPI外设,界面如下:
在这里插入图片描述

拉低CS->写数据->拉高CS,代码如下:

uint8_t hello_str[] = "hello from the SAM E70 X PLAINED ultra";
int main ( void )
{
    /* Initialize all modules */
    SYS_Initialize ( NULL );
    printf("%s at %s %s\r\n", hello_str, __DATE__, __TIME__);

    EXT1_SPI_CS_Clear();
    SPI0_Write(hello_str, sizeof(hello_str));
    while(SPI0_IsTransmitterBusy());
    EXT1_SPI_CS_Set();

    while ( true )
    {
        LED3_Toggle();
        SYSTICK_DelayMs(500);
        /* Maintain state machines of all polled MPLAB Harmony modules. */
        SYS_Tasks ( );
    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}

使用逻辑分析仪抓取数据,效果如下:
在这里插入图片描述

SPI我们使用的是模式0(CPOL=0,CPHA=0),放大后波形如下:
在这里插入图片描述

PWM

脉冲宽度调制(Pulse Width Modulation,PWM),使用图形界面配置如下,这里初始占空比设置为50%。
在这里插入图片描述

在main函数中使能输出,代码如下:

uint8_t hello_str[] = "hello from the SAM E70 X PLAINED ultra";
int main ( void )
{
    /* Initialize all modules */
    SYS_Initialize ( NULL );
    printf("%s at %s %s\r\n", hello_str, __DATE__, __TIME__);

    PWM0_ChannelsStart(PWM_CHANNEL_0_MASK);

    while ( true )
    {
        LED3_Toggle();
        SYSTICK_DelayMs(500);
        /* Maintain state machines of all polled MPLAB Harmony modules. */
        SYS_Tasks ( );
    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}

使用逻辑分析仪抓取波形,数据如下:
在这里插入图片描述

修改占空比为75%,代码如下:

uint8_t hello_str[] = "hello from the SAM E70 X PLAINED ultra";
int main ( void )
{
    /* Initialize all modules */
    SYS_Initialize ( NULL );
    printf("%s at %s %s\r\n", hello_str, __DATE__, __TIME__);

    PWM0_REGS->PWM_CH_NUM[0].PWM_CDTY = PWM0_ChannelPeriodGet(PWM_CHANNEL_0) / 4 * 3;
    PWM0_ChannelsStart(PWM_CHANNEL_0_MASK);

    while ( true )
    {
        LED3_Toggle();
        SYSTICK_DelayMs(500);
        /* Maintain state machines of all polled MPLAB Harmony modules. */
        SYS_Tasks ( );
    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}

使用逻辑分析仪抓取波形,数据如下:
在这里插入图片描述
本篇简单学习了IIC主机、从机、SPI主机的基本使用,中断,DMA传输等暂未设计,感兴趣可以自行添加测试。接下来将开始学习对存储单元的操作(读写Flash)等。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐