User Tools

Site Tools

blog:2024-01-25_share_stm32單片機控制a1333角度傳感器磁編碼器



2024-01-25 Share: STM32單片機控制A1333角度傳感器磁編碼器

  • This article describes the example for A1333 angle sensor control by STM32

Local Backup

A1333角度傳感器

  • 美國ALLEGRO型號A1333是一款360°角度傳感器IC,可基於磁性圓形垂直霍爾(CVH)技術提供無接觸,低延遲,高分辨率的角位置信息。它具有系統片上(SoC)架構,包括:CVH前端,數字信號處理和電機換向(UVW)或編碼器輸出(A,B,I)。它還包括片上EEPROM技術,能夠支持多達100個讀/寫週期,以便對校準參數進行靈活的終端編程。芯片圖片:
  • 結構框圖:

硬件安裝

  • A1333是一款360°角度傳感器IC,被測量部件可以採用永磁鐵,並確保使用過程沒有強磁干擾。由於測量的一般都是旋轉部件,則採用圓形銣磁鐵即可,此處需要注意圓形磁鐵的極化方向,分爲軸向和徑向兩種。根據芯片測量原理,我們需要採用徑向銣磁鐵。
  • 採用直徑10mm,厚度2.5mm圓形銣磁鐵即可,磁鐵軸心與芯片中心,需要儘可能在同一點上,若磁鐵和芯片不在同一直線上,也會出現測量誤差,示意圖如下圖:
  • 裝配時,銣磁鐵與芯片之間的間隙,需要儘可能小,數據手冊中有磁強和間隙大小以及角度誤差之間的關係,爲了減小誤差建議間隙2mm以內。本文最終採用的銣磁鐵如下:

通信接口

  • A1333有兩種編程方式:1.使用SPI接口進行輸入和輸出;2.輸入使用曼徹斯特協議,輸出使用PWM協議。本文使用SPI接口進行通信,所以只對SPI相關參數進行介紹。A1333的SPI接口提供四線全雙工模式,CPHA=1,CPOL=1,總線時鐘最低支持100KHz,最高支持10MHz,兼容3.3V和5V的IO模式。經典接線圖如下:
  • A1333有三種數據幀格式,分別是16位、17位和20位的幀格式,其中20位幀格式實際上是16位數據加4位CRC校驗位擴展而來,17位幀格式只有在使用擴展E2PROM才使用。如下圖:

寫寄存器

  • 寫寄存器的數據幀格式由1bit的低位、1bit的R/W標誌位(bit=1)、6bit的地址位和8bit的數據位組成,還可以拼接可選的4bitCRC校驗位,如下圖所示(注意MOSI線):

讀寄存器

  • 讀寄存器的操作,由至少兩次SPI交互組成,第一次交互先發送需要讀取的寄存器信息,此時讀取回來的數據爲上一次操作的數據;第二次可以發送一個空操作(讀0x00寄存器)信息,此時讀取回來的數據爲所需的寄存器數據,其中第二次交互發送的數據幀,還可以是讀操作數據幀,這樣第三次交互就可以接到第二次讀操作的數據了。讀寄存器的數據幀格式由1bit的低位、1bit的R/W標誌位(bit=0)、6bit的地址位和8bit的0組成,同樣可以拼接4bit的CRC校驗位。如下圖所示:

寄存器

  • 這裏主要介紹角度數據寄存器(0x32)和key寄存器(0x3c)。操作A1333的寄存器前,需要操作key寄存器進行解鎖。

數據寄存器(0x32)

  • 讀取出來的是15位數據,角度轉換公式:ANGLE_15 × (360/32768)

Key寄存器(0x3c)

  • 在寄存器操作前,需要先操作key寄存器進行解鎖,解鎖方法爲向key寄存器寫入5組KEYCODE,解鎖成功後纔可以進行其他寄存器操作,KEYCODE如下表:
  • Write	CODE
    1	0x00
    2	0x27
    3	0x81
    4	0x1F
    5	0x77

STM32控制部分

電路原理圖

程序

  • a1333.c
    #include "a1333.h"
    
    const uint16_t WRITE = 0x40;
    const uint16_t READ = 0x00;
    const uint16_t COMMAND_MASK = 0xC0;
    const uint16_t ADDRESS_MASK = 0x3F;
    
    #define CS_H()	GPIO_SetBits(GPIOB,GPIO_Pin_12)
    #define CS_L()	GPIO_ResetBits(GPIOB,GPIO_Pin_12)
    
    static uint16_t spi2_rw(uint16_t cmd,uint16_t *value)
    {
    	u8 retry=0;	
    	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
    	{
    		retry++;
    		if(retry>200)return 0;
    	}
    	SPI_I2S_SendData(SPI2, cmd); 
    	retry=0;
     
    	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) 
    	{
    		retry++;
    		if(retry>200)return 0;
    	}
    	if(value){
    		*value = SPI_I2S_ReceiveData(SPI2);
    	}else{
    		SPI_I2S_ReceiveData(SPI2);
    	}
    	
    	return 1;
    }
    
    
    static uint16_t PrimaryWrite(uint16_t address, uint16_t value)
    {
    	u8 s=0;
    	uint16_t command = ((address & ADDRESS_MASK) | WRITE) << 8;
    	
    	CS_L();
    	Delay_1us(1);
    	s = spi2_rw(command | ((value >> 8) & 0x0FF),0);
    	CS_H();
    	if(s == 0){
    		return 0;
    	}
    	
    	command = (((address + 1) & ADDRESS_MASK) | WRITE) << 8;
    	CS_L();
    	Delay_1us(1);
    	s = spi2_rw(command | (value & 0x0FF),0);
    	CS_H();
    	if(s == 0){
    		return 0;
    	}
    	return 1;
    }
    
    static uint16_t PrimaryRead(uint16_t address, uint16_t *value)
    {
    	u8 s=1;		
    	uint16_t command = ((address & ADDRESS_MASK) | READ) << 8;
    	CS_L();
    	Delay_1us(1);
    	s = spi2_rw(command,0);
    	CS_H();
    	if(s)
    	{
    		CS_L();
    		s = spi2_rw(command,value);
    		CS_H();
    		if(s)
    		{
    			return 1;
    		}
    		return 0;
    	}else{
    		return 0;
    	}
    }
    
    void a1333_init(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	SPI_InitTypeDef  SPI_InitStructure;
    
    	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );
    	RCC_APB1PeriphClockCmd(	RCC_APB1Periph_SPI2,  ENABLE );
    
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOB, &GPIO_InitStructure);
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOB, &GPIO_InitStructure);
    	
    	GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); 
    
    	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; 
    	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		
    	SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;		
    	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;		
    	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;	
    	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		
    	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;		
    	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    	SPI_Init(SPI2, &SPI_InitStructure);  
    
    	SPI_Cmd(SPI2, ENABLE);
    	
    	SPI_I2S_ClearFlag(SPI2, SPI_I2S_FLAG_RXNE);
    	
    	
    	{
    		u16 t = 0,flags;
    		PrimaryRead(0x00,&t);
    		
    			// Unlock the device
    		PrimaryWrite(0x3C, 0x2700);
    		PrimaryWrite(0x3C, 0x8100);
    		PrimaryWrite(0x3C, 0x1F00);
    		PrimaryWrite(0x3C, 0x7700);
    
    		// Make sure the device is unlocked
    		t = 100;
    		PrimaryRead(0x3C, &flags);
    		while ((flags & 0x0001) != 0x0001)
    		{
    			Delay_1us(10);
    			t--;
    			if (t==0)
    			{
    				LedSet(LED1);
    				LedReset(LED2);
    				while(1){
    					LedReverse(LED1 | LED2);
    					Delay_1ms(200);
    				}
    			}
    			PrimaryRead(0x3C, &flags);
    		}
    	}
    }
    
    uint16_t a1333_read_angle15(void){
    	uint16_t read_angle = 0;
    	PrimaryRead(0x32, &read_angle);
    	read_angle = read_angle & 0x7fff;
    	return read_angle;
    }
    
    uint16_t a1333_read_angle15_smooth(uint8_t sm){
    	uint8_t i;
    	uint32_t total = 0;
    	for(i=0;i<sm;i++){
    		total += a1333_read_angle15();
    	}
    	return total / sm;
    }
  • a1333.h
    #ifndef __A1333_H__
    #define __A1333_H__
    
    #include "stm32f10x.h"
    
    void a1333_init(void);
    uint16_t a1333_read_angle15(void);
    uint16_t a1333_read_angle15_smooth(uint8_t sm);
    
    #endif

TAGS

  • 38 person(s) visited this page until now.

Permalink blog/2024-01-25_share_stm32單片機控制a1333角度傳感器磁編碼器.txt · Last modified: 2024/01/25 15:15 by jethro

oeffentlich