mspm0G3507与ATK-IMU901十轴陀螺仪模块结合使用指南(附Keil源码)

开始:硬件连接 

源代码链接:链接:https://pan.baidu.com/–s/1m69UXBf2TM__1FVuUxfPgA?pwd=nhcu 
提取码:nhcu 

自己去掉中间的“–”,防和谐
 

电赛来临,相比大家已经做好了很多的准备,我本来使用的是普通的6050陀螺仪,但是发现这个的静态偏差挺大的,所以想着用一个好一点的陀螺仪就买了正点原子的这个陀螺仪。

我使用的是mspm0g3507,但是正点原子并没有给出相应的代码所以就需要自己去移植,自己琢磨了一下,难度不是很高,但是要去翻手册,想必很多萌新都不太愿意去看(也有可能是因为找不到哈哈)就出了这个教程。(L1306理论上也是可以使用的,串口稍微有点区别)

其中我自己遇到了一个问题,因为一次性接受的数据很多,而且有时候发送过来并没有接收就会导致串口FIFO接收满了导致OVERRUN_ERROR(串口接收溢出错误),stm32有很多相关的教程,但是g3507几乎没有,在我翻了driverlib的库和一些stm32的解决办法后将他解决了,就在修改UART.C文件标题里面。话不多说,开始教程吧!

首先我们准备正点原子的陀螺仪模块,如下图

然后将模块的tx 和rx 与我们开发板的串口相连接(tx连接我们主板的rx,rx连接我们主板的tx)

我使用的是串口3(pa13(rx)和pa14(tx),每个人设置的不一样可能有差别)如下图所示

引脚配置:串口3 

sysconfig引脚配置如图所示

波特率可以自行修改,interrupt configuration必须是overrun error(接收溢出错误)和receive(接收)两个中断!!!

代码移植:

正点原子代码

开始之前先将串口3的中断进行使能,不然没法用

我们首先要得到一份正点原子官方的代码文件:如下图所示(百度直接搜索正点原子资料下载或者问客服要就行)

路径:

然后我们将精英stm32f103压缩包解压得到一个文件夹,点进去之后进入Drivers这个文件夹下面的BSP,我们会看到以下几个文件夹

拷贝文件:

我们将ATK_MS901M整个文件夹拷贝到你自己的工程下面去!!里面是有四个文件的!!!

添加.c和.h文件

在keil中去添加.c和.h文件(这个不会的话去看野火的stm32教程,开始就讲了,这里就不多说了)

添加好的文件(我是编译过的,前面有个小加号,最开始编译要报很多的错误,先不要编译)

修改UART.h文件

仔细看一下两个.c文件,atk_ms901.c文件里面都是一些功能函数,和陀螺仪读取数据相关的,我们不用去管它(包括atk_ms901.h也不用去管),我们把重点放在(后续为了方便将atk_ms901_uart.c和atk_ms901_uart.h统一叫做uart.c和uart.h)uart.c和uart.h的文件上面

首先我们打开uart.h文件,将引脚定义的代码全部都注释掉,这是基于hal库写的,我们有sysconfig,使能什么的都已经帮我们做好了(缓冲区大小你们没必要写我这么大,原来不变就行)

修改UART.C文件

uart.c文件里面我们主要是要修改以下几个函数

void atk_ms901m_uart_send(uint8_t *dat, uint8_t len)
{
    HAL_UART_Transmit(&g_uart_handle, dat, len, HAL_MAX_DELAY);
}

/**
 * @brief       ATK-MS901M UART初始化
 * @param       baudrate: UART通讯波特率
 * @retval      无
 */
void atk_ms901m_uart_init(uint32_t baudrate)
{
    g_uart_handle.Instance          = ATK_MS901M_UART_INTERFACE;    /* ATK-MS901M UART */
    g_uart_handle.Init.BaudRate     = baudrate;                     /* 波特率 */
    g_uart_handle.Init.WordLength   = UART_WORDLENGTH_8B;           /* 数据位 */
    g_uart_handle.Init.StopBits     = UART_STOPBITS_1;              /* 停止位 */
    g_uart_handle.Init.Parity       = UART_PARITY_NONE;             /* 校验位 */
    g_uart_handle.Init.Mode         = UART_MODE_TX_RX;              /* 收发模式 */
    g_uart_handle.Init.HwFlowCtl    = UART_HWCONTROL_NONE;          /* 无硬件流控 */
    g_uart_handle.Init.OverSampling = UART_OVERSAMPLING_16;         /* 过采样 */
    HAL_UART_Init(&g_uart_handle);                                  /* 使能ATK-MS901M UART
                                                                     * HAL_UART_Init()会调用函数HAL_UART_MspInit()
                                                                     * 该函数定义在文件usart.c中
                                                                     */
    g_uart_rx_fifo.size = ATK_MS901M_UART_RX_FIFO_BUF_SIZE;         /* UART接收FIFO缓冲大小 */
    g_uart_rx_fifo.reader = 0;                                      /* UART接收FIFO读指针 */
    g_uart_rx_fifo.writer = 0;                                      /* UART接收FIFO写指针 */
}

/**
 * @brief       ATK-MS901M UART中断回调函数
 * @param       无
 * @retval      无
 */
void ATK_MS901M_UART_IRQHandler(void)
{
    uint8_t tmp;
    
    if (__HAL_UART_GET_FLAG(&g_uart_handle, UART_FLAG_ORE) != RESET)    /* UART接收过载错误中断 */
    {
        __HAL_UART_CLEAR_OREFLAG(&g_uart_handle);                       /* 清除接收过载错误中断标志 */
        (void)g_uart_handle.Instance->SR;                               /* 先读SR寄存器,再读DR寄存器 */
        (void)g_uart_handle.Instance->DR;
    }
    
    if (__HAL_UART_GET_FLAG(&g_uart_handle, UART_FLAG_RXNE) != RESET)   /* UART接收中断 */
    {
        HAL_UART_Receive(&g_uart_handle, &tmp, 1, HAL_MAX_DELAY);       /* UART接收数据 */
        atk_ms901m_uart_rx_fifo_write(&tmp, 1);                         /* 接收到的数据,写入UART接收FIFO */
    }
}

修改后的函数:

void atk_ms901m_uart_send(char *dat, uint8_t len)
{
    //HAL_UART_Transmit(&g_uart_handle, dat, len, HAL_MAX_DELAY);
	      //当前字符串地址不在结尾 并且 字符串首地址不为空
    while(*dat!=0&&dat!=0)
    {
        //发送字符串首地址中的字符,并且在发送完成之后首地址自增
        uart3_send_char(*dat++);
    }
}

/**
 * @brief       ATK-MS901M UART初始化
 * @param       baudrate: UART通讯波特率
 * @retval      无
 */
void atk_ms901m_uart_init(uint32_t baudrate)
{                                                                   
    g_uart_rx_fifo.size = ATK_MS901M_UART_RX_FIFO_BUF_SIZE;         /* UART接收FIFO缓冲大小 */
    g_uart_rx_fifo.reader = 0;                                      /* UART接收FIFO读指针 */
    g_uart_rx_fifo.writer = 0;                                      /* UART接收FIFO写指针 */
}

/**
 * @brief       ATK-MS901M UART中断回调函数
 * @param       无
 * @retval      无
 */
void UART_3_INST_IRQHandler(void)
{
    uint8_t tmp;
	switch( DL_UART_getPendingInterrupt(UART_3_INST) )
	{
		case DL_UART_IIDX_OVERRUN_ERROR:
			DL_UART_getRawInterruptStatus(UART_3_INST,DL_UART_IIDX_OVERRUN_ERROR);
		  DL_UART_Main_receiveData(UART_3_INST);
			break;
		case DL_UART_IIDX_RX://如果是接收中断			
			// 接收发送过来的数据保存
			tmp = DL_UART_Main_receiveData(UART_3_INST);
      atk_ms901m_uart_rx_fifo_write(&tmp, 1);
			break;	
		default://其他的串口中断
			break;
	}
	DL_UART_clearInterruptStatus(UART_3_INST,DL_UART_IIDX_OVERRUN_ERROR);
	
}

其中uart3_send_char(*dat++);函数的实现如下

void uart3_send_char(char ch)
{
    //当串口3忙的时候等待,不忙的时候再发送传进来的字符
    while( DL_UART_isBusy(UART_3_INST) == true );
    DL_UART_Main_transmitData(UART_3_INST, ch);
}

在修改完中断回调函数之后请将uart.h文件里面的中断回调函数的名称改掉!!!!

调试:DEMO.C

我们返回刚才的精英stm32f103文件夹,进入Projects->MDK-ARM->atk_f103.uvprojx,打开工程文件之后我们点击demo.c文件,copy其中的有用代码,如下所示:

void demo_run(void)
{
 uint8_t ret;
 uint8_t key;
 
 /* 初始化 ATK-MS901M */
 ret = atk_ms901m_init(115200);
 if (ret != 0)
 {
 printf("ATK-MS901M init failed!\r\n");
	 delay_ms(1000);
 }
 //printf("ATK-MS901M init success!\r\n\n"); 
 demo_key0_fun();
 delay_ms(10);
 }
 
 


 void demo_key0_fun(void)
{
    atk_ms901m_attitude_data_t attitude_dat;           /* 姿态角数据 */
    atk_ms901m_gyro_data_t gyro_dat;                   /* 陀螺仪数据 */
    atk_ms901m_accelerometer_data_t accelerometer_dat; /* 加速度计数据 */
    atk_ms901m_magnetometer_data_t magnetometer_dat;   /* 磁力计数据 */
    atk_ms901m_barometer_data_t barometer_dat;         /* 气压计数据 */   
    /* 获取ATK-MS901数据 */
    atk_ms901m_get_attitude(&attitude_dat, 100);                            /* 获取姿态角数据 */
    atk_ms901m_get_gyro_accelerometer(&gyro_dat, &accelerometer_dat, 100);  /* 获取陀螺仪、加速度计数据 */
    atk_ms901m_get_magnetometer(&magnetometer_dat, 100);                    /* 获取磁力计数据 */
    atk_ms901m_get_barometer(&barometer_dat, 100);                          /* 获取气压计数据 */    
    /* 串口打印数据 */
    printf("Roll: %.02f Pitch: %.02f Yaw: %.02f\r\n", attitude_dat.roll, attitude_dat.pitch, attitude_dat.yaw);
    printf("Gx: %.02f/s Gy: %.02f/s Gz: %.02f/s\r\n", gyro_dat.x, gyro_dat.y, gyro_dat.z);
    printf("Ax: %.02fG Ay: %.02fG Az: %.02fG\r\n", accelerometer_dat.x, accelerometer_dat.y, accelerometer_dat.z);
    printf("Mx: %d My: %d Mz: %d, Temp: %.02f\r\n", magnetometer_dat.x, magnetometer_dat.y, magnetometer_dat.z, magnetometer_dat.temperature);
    printf("Pres: %dPa Alt: %dcm Temp: %.02f\r\n", barometer_dat.pressure, barometer_dat.altitude, barometer_dat.temperature);
    printf("****************************************\r\n\r\n");
}

运行:

然后我们将demo_run()文件放在while循环中就能使用了,效果如下:(打印的初始化错误是错的,实际上没有问题,我懒得去修改了),可以看见有很多参数,这就是这款陀螺仪的好处,参数很多,角度,加速度,还有磁力计,四元数,气压,海拔高度等

作者:Aufstiegen aus Ruine

物联沃分享整理
物联沃-IOTWORD物联网 » mspm0G3507与ATK-IMU901十轴陀螺仪模块结合使用指南(附Keil源码)

发表回复