PIC16F18xx软/硬件SPI驱动磁性传感器AS5045B(附SPI模式分辨方法)

刚入职时做项目用到了PIC这款单片机,以前没有接触过,只能速成。

我直接使用了MCC对芯片引脚及外设进行了配置。

如果有什么不对的地方欢迎大家指出改正。 


 MCC使用文档

MAPLab X IDE用户指南

开发帮助https://microchipdeveloper.com/projects:mcu1101-project-12icon-default.png?t=N7T8https://microchipdeveloper.com/projects:mcu1101-project-12

 系统使用的内部振荡器

PIC的SPI四种模式,和标准有些区别


引脚配置 

根据芯片手册中的时序图,选择SPI的模式一。MCU作为主机。

当时我debug观察变量,发现数据稳定是稳定了,但是会发生2倍跳变,然后再稳定,这样肯定不对。

于是我使用了模拟IO方法,读出了稳定的值,再慢慢更改模式,最终发现是在采样输入数据配置中出了问题,是选择“END”而不是中间。


 配置完后给IO口重命名,查看输入输出的配置是否正确。

中断这里也要勾上。我没有注意到要打开中断外设使能,导致串口中断不能使用。

在刚创建好工程那会我翻开了下代码,唯独没有注意头文件藏着封装好的函数。 

#include "interrupt_manager.h"

在主函数中系统初始化后加入:

void main(void)
{
    SYSTEM_Initialize();
    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();
    spi_master_open(MASTER1);
    while (1)
    {
         Send485();
         dat=Read_Angle();
         Angle=(dat>>4)*0.00879*10;    //y = 11.375x + 0.1667
//        dat=Sim_Angle_Dout();
//        Angle=dat*0.00879*10;
    }
}

AS5045B.c

 我只需要读出高12位的值即可,后面的校验位等信息暂时不用关心。后面的OTP编程模式看起来很复杂,我也没有去了解。

#include "AS5045B.h"
#include "mcc.h"

/*******硬件SPI*********/
uint16_t Read_Angle()  
{
    uint8_t dat1,dat2;
    uint16_t a;
    SPI_CS_SetLow();
//    DELAY_milliseconds(1);
//    RC0_SetHigh();
    DELAY_milliseconds(1);
    dat1= SPI_ExchangeByte(0);
    dat2= SPI_ExchangeByte(0);
    SPI_CS_SetHigh();
    DELAY_milliseconds(1);
//    RC0_SetHigh();
    a=(uint16_t)((dat1<<8)|dat2);
    return a;
}

/********IO模拟SPI*********/
uint16_t Sim_Angle_Dout()
{
    uint16_t out;
    uint8_t i;
    out=0;        
    SPI_CS_SetHigh(); 
    RC0_SetHigh(); 
    SPI_CS_SetLow();         //数据输出DO从变为高电平并启动读取操作
    DELAY_microseconds(2);
    RC0_SetLow();       //数据在CLK第一个下降沿锁存至输出移位寄存器中
    DELAY_microseconds(2);
    for(i=0;i<12;i++)    //循环取高12位角度信息
    {
        out=out<<1;
        RC0_SetHigh();
       //每个CLK上升沿移出一位数据
        DELAY_microseconds(2);
        out|=RC1_GetValue();
        DELAY_microseconds(2);
        RC0_SetLow();
        DELAY_microseconds(2);
    }

    DELAY_microseconds(2);
    SPI_CS_SetHigh();
    RC0_SetHigh();
    DELAY_microseconds(1);
    return (out);
}

 由于SPI是全双工通信,发的时候会接收到数据,所以接数据且不需要发送数据时候写个0就可以了 

时钟极性(CPOL)定义了时钟空闲状态电平:

CPOL=0,表示当SCLK=0时处于空闲态,所以有效状态就是SCLK处于高电平时
CPOL=1,表示当SCLK=1时处于空闲态,所以有效状态就是SCLK处于低电平时
        
时钟相位(CPHA)定义数据的采集时间:
CPHA=0,在时钟的第一个跳变沿进行数据采样,在第2个边沿发送数据
CPHA=1,在时钟的第二个跳变沿进行数据采样,在第1个边沿发送数据

        
例如:CPOL=0,CPHA=0时,

数据不传输时,CPOL为0是空闲;

数据传输时,CPHA=0要在第一个边沿进行数据采样,即从空闲开始CLK由低到高,数据采样在上升沿,发送在下降沿(第2个边沿)


SPI模式

SPI一共有四种模式,按二进制排序。(这里是STM32演示,和PIC的SPI定义的模式不同)

模式0:CPOL=0,CPHA=0

模式1:CPOL=0,CPHA=1

模式2:CPOL=1,CPHA=0

模式3:CPOL=1,CPHA=1

最易理解是看空闲电平和是第1个还是第二个边沿采集完数据。

以ADS1220为例

不传输数据时,SCLK=0.空闲时为0,CPOL=0;

传输数据大概是SCLK第二个边沿位置(第二个边沿可看出是高到低采集完一帧数据),即CPHA=1.

该芯片SPI模式为模式1

反之,不传输数据时,SCLK=1,即空闲时为1,CPOL=1;

传输数据在SCLK第一个边沿时,CPHA=0。

First Bit分为MSB和LSB,MSB代表起始地址高位,最低位是低位(大端)

LSB是起始地址低位,最低位是高位(小端)

随便找个芯片手册,寄存器长度是8位:

B7是最高的数据位,放在了最高位,B7先发出去,是大端,MSB。如果B0在最高位 ,先发出去,则是小端。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

随风飘零翼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值