zhai · 2022年04月27日

GD32F310定时器采样MP6050并在彩色LCD上显示波形

1.开发环境

(1)IAR8.4
(2)MPU6050 1.8寸显示屏

2.软件

(1)MPU6050陀螺仪驱动

i2C配置:

void i2c0_gpio_config(void)
{

rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_I2C0);  
gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_6);
gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_7);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_6);
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_7);
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_7);

}

void i2c_config(void)
{

i2c_clock_config(I2C0, 200000, I2C_DTCY_2);
i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE,     I2C_ADDFORMAT_7BITS, SlaveAddress);
i2c_enable(I2C0);
i2c_ack_config(I2C0, I2C_ACK_ENABLE);

}

uint8_t Read_Byte(uint16_t SlaveAddr,uint16_t ReadAddr, uint8_t *DataByte)
{

uint8_t err = 1;
i2c_start_on_bus(I2C0);                            
while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));    
i2c_master_addressing(I2C0, SlaveAddr<<1, I2C_TRANSMITTER); 
while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));    
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);            
while(!i2c_flag_get(I2C0, I2C_FLAG_TBE));        
i2c_data_transmit(I2C0, ReadAddr);    
while(!i2c_flag_get(I2C0, I2C_FLAG_TBE));    
i2c_start_on_bus(I2C0);                            
while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));    
i2c_master_addressing(I2C0, SlaveAddr<<1, I2C_RECEIVER);     
while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));    
i2c_ack_config(I2C0, I2C_ACK_DISABLE);            
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);            
i2c_stop_on_bus(I2C0);                            
while(!i2c_flag_get(I2C0, I2C_FLAG_RBNE));        
*DataByte  = i2c_data_receive(I2C0);            
i2c_ack_config(I2C0, I2C_ACK_ENABLE);            
err = 0;
return err;

}

uint8_t Write_Byte(uint16_t SlaveAddr,uint16_t WriteAddr,uint16_t WriteByte)
{

uint8_t err = 0;    
i2c_start_on_bus(I2C0);                            
while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));    
i2c_master_addressing(I2C0, SlaveAddr<<1, I2C_TRANSMITTER);
while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));    
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);            
while(!i2c_flag_get(I2C0, I2C_FLAG_TBE));        
i2c_data_transmit(I2C0, WriteAddr);                
while(!i2c_flag_get(I2C0, I2C_FLAG_TBE));        
i2c_data_transmit(I2C0, WriteByte);                
while(!i2c_flag_get(I2C0, I2C_FLAG_TBE));        
i2c_stop_on_bus(I2C0);                            
return err;

}

陀螺仪初始化:

void mpu6050_init(){

Write_Byte( SlaveAddress, PWR_MGMT_1,  0x00 );
delay_1ms(10);
Write_Byte( SlaveAddress, SMPLRT_DIV,  0x07 );
delay_1ms(10);

Write_Byte( SlaveAddress, CONFIG, 0x06 );
delay_1ms(10);


Write_Byte( SlaveAddress, GYRO_CONFIG,  0x18);
delay_1ms(10);
Write_Byte( SlaveAddress, ACCEL_CONFIG,  0x01);
delay_1ms(10);

}

void GetData(uint16_t SlaveAddr,uint16_t REG_Address,short data[3])
{

uint8_t H=0,L=0;

for(int i=0;i<3;i++){
    Read_Byte(SlaveAddress, REG_Address+(i*2), &H);
    Read_Byte( SlaveAddress, REG_Address+(i*2+1),&L); 
   data[i]=(( short)(H<<8))|L;

}

(2)LCD驱动

驱动:

void LCD_GPIO_Init(void)
{


     rcu_periph_clock_enable(RCU_GPIOA);
     gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5);
     gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5);
     gpio_bit_set(GPIOA,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5);

}

void LCD_Writ_Bus(uint8_t dat)
{

uint8_t i;
LCD_CS_Clr();
for(i=0;i<8;i++)
{              
    LCD_SCLK_Clr();
    if(dat&0x80)
    {
       LCD_MOSI_Set();
    }
    else
    {
       LCD_MOSI_Clr();
    }
    LCD_SCLK_Set();
    dat<<=1;
}    

LCD_CS_Set();

}

void LCD_WR_DATA8(uint8_t dat)
{

LCD_Writ_Bus(dat);

}

void LCD_WR_DATA(uint16_t dat)
{

LCD_Writ_Bus(dat>>8);
LCD_Writ_Bus(dat);

}

void LCD_WR_REG(uint8_t dat)
{

LCD_DC_Clr();//д????
LCD_Writ_Bus(dat);
LCD_DC_Set();//д????

}

void LCD_Address_Set(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2)
{

if(USE_HORIZONTAL==0)
{
    LCD_WR_REG(0x2a);//?е??????
    LCD_WR_DATA(x1+2);
    LCD_WR_DATA(x2+2);
    LCD_WR_REG(0x2b);//?е??????
    LCD_WR_DATA(y1+1);
    LCD_WR_DATA(y2+1);
    LCD_WR_REG(0x2c);//??????д
}
else if(USE_HORIZONTAL==1)
{
    LCD_WR_REG(0x2a);//?е??????
    LCD_WR_DATA(x1+2);
    LCD_WR_DATA(x2+2);
    LCD_WR_REG(0x2b);//?е??????
    LCD_WR_DATA(y1+1);
    LCD_WR_DATA(y2+1);
    LCD_WR_REG(0x2c);//??????д
}
else if(USE_HORIZONTAL==2)
{
    LCD_WR_REG(0x2a);//?е??????
    LCD_WR_DATA(x1+1);
    LCD_WR_DATA(x2+1);
    LCD_WR_REG(0x2b);//?е??????
    LCD_WR_DATA(y1+2);
    LCD_WR_DATA(y2+2);
    LCD_WR_REG(0x2c);//??????д
}
else
{
    LCD_WR_REG(0x2a);//?е??????
    LCD_WR_DATA(x1+1);
    LCD_WR_DATA(x2+1);
    LCD_WR_REG(0x2b);//?е??????
    LCD_WR_DATA(y1+2);
    LCD_WR_DATA(y2+2);
    LCD_WR_REG(0x2c);//??????д
}

}

void LCD_Init(void)
{

LCD_GPIO_Init();

LCD_RES_Clr();
delay_1ms(100);
LCD_RES_Set();
delay_1ms(100);

LCD_BLK_Set();
    delay_1ms(100);


delay_1ms(120);             

LCD_WR_REG(0xB1); 
LCD_WR_DATA8(0x05); 
LCD_WR_DATA8(0x3C); 
LCD_WR_DATA8(0x3C); 
LCD_WR_REG(0xB2); 
LCD_WR_DATA8(0x05);
LCD_WR_DATA8(0x3C); 
LCD_WR_DATA8(0x3C); 
LCD_WR_REG(0xB3); 
LCD_WR_DATA8(0x05); 
LCD_WR_DATA8(0x3C); 
LCD_WR_DATA8(0x3C); 
LCD_WR_DATA8(0x05); 
LCD_WR_DATA8(0x3C); 
LCD_WR_DATA8(0x3C); 

LCD_WR_REG(0xB4); //Dot inversion 
LCD_WR_DATA8(0x03); 

LCD_WR_REG(0xC0); 
LCD_WR_DATA8(0x28); 
LCD_WR_DATA8(0x08); 
LCD_WR_DATA8(0x04); 
LCD_WR_REG(0xC1); 
LCD_WR_DATA8(0XC0); 
LCD_WR_REG(0xC2); 
LCD_WR_DATA8(0x0D); 
LCD_WR_DATA8(0x00); 
LCD_WR_REG(0xC3); 
LCD_WR_DATA8(0x8D); 
LCD_WR_DATA8(0x2A); 
LCD_WR_REG(0xC4); 
LCD_WR_DATA8(0x8D); 
LCD_WR_DATA8(0xEE); 

LCD_WR_REG(0xC5); //VCOM 
LCD_WR_DATA8(0x1A); 
LCD_WR_REG(0x36); //MX, MY, RGB mode 
if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x00);
else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC0);
else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x70);
else LCD_WR_DATA8(0xA0); 

LCD_WR_REG(0xE0); 
LCD_WR_DATA8(0x04); 
LCD_WR_DATA8(0x22); 
LCD_WR_DATA8(0x07); 
LCD_WR_DATA8(0x0A); 
LCD_WR_DATA8(0x2E); 
LCD_WR_DATA8(0x30); 
LCD_WR_DATA8(0x25); 
LCD_WR_DATA8(0x2A); 
LCD_WR_DATA8(0x28); 
LCD_WR_DATA8(0x26); 
LCD_WR_DATA8(0x2E); 
LCD_WR_DATA8(0x3A); 
LCD_WR_DATA8(0x00); 
LCD_WR_DATA8(0x01); 
LCD_WR_DATA8(0x03); 
LCD_WR_DATA8(0x13); 
LCD_WR_REG(0xE1); 
LCD_WR_DATA8(0x04); 
LCD_WR_DATA8(0x16); 
LCD_WR_DATA8(0x06); 
LCD_WR_DATA8(0x0D); 
LCD_WR_DATA8(0x2D); 
LCD_WR_DATA8(0x26); 
LCD_WR_DATA8(0x23); 
LCD_WR_DATA8(0x27); 
LCD_WR_DATA8(0x27); 
LCD_WR_DATA8(0x25); 
LCD_WR_DATA8(0x2D); 
LCD_WR_DATA8(0x3B); 
LCD_WR_DATA8(0x00); 
LCD_WR_DATA8(0x01); 
LCD_WR_DATA8(0x04); 
LCD_WR_DATA8(0x13); 
//------------------------------------End ST7735S Gamma Sequence-----------------------------// 
LCD_WR_REG(0x3A); //65k mode 
LCD_WR_DATA8(0x05); 
LCD_WR_REG(0x29); //Display on 

}

显示函数:

void LCD_Fill(uint16_t xsta,uint16_t ysta,uint16_t xend,uint16_t yend,uint16_t color)
{

uint16_t i,j; 
LCD_Address_Set(xsta,ysta,xend-1,yend-1);//?????????Χ
for(i=ysta;i<yend;i++)
{                                                                
    for(j=xsta;j<xend;j++)
    {
        LCD_WR_DATA(color);
    }
}                               

}

void LCD_DrawPoint(uint16_t x,uint16_t y,uint16_t color)
{

LCD_Address_Set(x,y,x,y);//???ù??λ?? 
LCD_WR_DATA(color);

}

void LCD_DrawLine(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2,uint16_t color)
{

uint16_t t; 
int xerr=0,yerr=0,delta_x,delta_y,distance;
int incx,incy,uRow,uCol;
delta_x=x2-x1; //???????????? 
delta_y=y2-y1;
uRow=x1;//???????????
uCol=y1;
if(delta_x>0)incx=1; //??????????? 
else if (delta_x==0)incx=0;//????? 
else {incx=-1;delta_x=-delta_x;}
if(delta_y>0)incy=1;
else if (delta_y==0)incy=0;//???? 
else {incy=-1;delta_y=-delta_y;}
if(delta_x>delta_y)distance=delta_x; //???????????????? 
else distance=delta_y;
for(t=0;t<distance+1;t++)
{
    LCD_DrawPoint(uRow,uCol,color);//????
    xerr+=delta_x;
    yerr+=delta_y;
    if(xerr>distance)
    {
        xerr-=distance;
        uRow+=incx;
    }
    if(yerr>distance)
    {
        yerr-=distance;
        uCol+=incy;
    }
}

}

void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2,uint16_t color)
{

LCD_DrawLine(x1,y1,x2,y1,color);
LCD_DrawLine(x1,y1,x1,y2,color);
LCD_DrawLine(x1,y2,x2,y2,color);
LCD_DrawLine(x2,y1,x2,y2,color);

}

void Draw_Circle(uint16_t x0,uint16_t y0,uint8_t r,uint16_t color)
{

int a,b;
a=0;b=r;      
while(a<=b)
{
    LCD_DrawPoint(x0-b,y0-a,color);                    
    LCD_DrawPoint(x0+b,y0-a,color);                       
    LCD_DrawPoint(x0-a,y0+b,color);                            
    LCD_DrawPoint(x0-a,y0-b,color);                        
    LCD_DrawPoint(x0+b,y0+a,color);                         
    LCD_DrawPoint(x0+a,y0-b,color);            
    LCD_DrawPoint(x0+a,y0+b,color);              
    LCD_DrawPoint(x0-b,y0+a,color);             
    a++;
    if((a*a+b*b)>(r*r))
    {
        b--;
    }
}

}

void LCD_ShowChar(uint16_t x,uint16_t y,uint8_t num,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode)
{

uint8_t temp,sizex,t,m=0;
uint16_t i,TypefaceNum;
uint16_t x0=x;
sizex=sizey/2;
TypefaceNum=(sizex/8+((sizex%8)?1:0))*sizey;
num=num-' ';   
LCD_Address_Set(x,y,x+sizex-1,y+sizey-1); 
for(i=0;i<TypefaceNum;i++)
{ 
    if(sizey==12)temp=ascii_1206[num][i];               
    else if(sizey==16)temp=ascii_1608[num][i];         
    else if(sizey==24)temp=ascii_2412[num][i];         
    else if(sizey==32)temp=ascii_3216[num][i];         
    else return;
    for(t=0;t<8;t++)
    {
        if(!mode)//???????
        {
            if(temp&(0x01<<t))LCD_WR_DATA(fc);
            else LCD_WR_DATA(bc);
            m++;
            if(m%sizex==0)
            {
                m=0;
                break;
            }
        }
        else
        {
            if(temp&(0x01<<t))LCD_DrawPoint(x,y,fc);
            x++;
            if((x-x0)==sizex)
            {
                x=x0;
                y++;
                break;
            }
        }
    }
}              

}

void LCD_ShowString(uint16_t x,uint16_t y,const uint8_t *p,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode)
{

while(*p!='\0')
{       
    LCD_ShowChar(x,y,*p,fc,bc,sizey,mode);
    x+=sizey/2;
    p++;
}  

}

uint32_t mypow(uint8_t m,uint8_t n)
{

uint32_t result=1;     
while(n--)result*=m;
return result;

}

void LCD_ShowIntNum(uint16_t x,uint16_t y,uint16_t num,uint8_t len,uint16_t fc,uint16_t bc,uint8_t sizey)
{

uint8_t t,temp;
uint8_t enshow=0;
uint8_t sizex=sizey/2;
for(t=0;t<len;t++)
{
    temp=(num/mypow(10,len-t-1))%10;
    if(enshow==0&&t<(len-1))
    {
        if(temp==0)
        {
            LCD_ShowChar(x+t*sizex,y,' ',fc,bc,sizey,0);
            continue;
        }else enshow=1; 
          
    }
     LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0);
}

}

void LCD_ShowFloatNum1(uint16_t x,uint16_t y,float num,uint8_t len,uint16_t fc,uint16_t bc,uint8_t sizey)
{

uint8_t t,temp,sizex;
uint16_t num1;
sizex=sizey/2;
num1=num*100;
for(t=0;t<len;t++)
{
    temp=(num1/mypow(10,len-t-1))%10;
    if(t==(len-2))
    {
        LCD_ShowChar(x+(len-2)*sizex,y,'.',fc,bc,sizey,0);
        t++;
        len+=1;
    }
     LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0);
}

}

(3)主函数

void gd_led_config(void);
void gd_led_toggle(void);

int data[128]={0},data2[128]={0},data3[128]={0};
short Acc[3],Gyro[3];

void TIMER2_IRQHandler(void) {

if(SET == timer_interrupt_flag_get(TIMER2, TIMER_INT_FLAG_UP)){
    /* clear channel 0 interrupt bit */
    timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_UP);
            
            
            
            GetData(SlaveAddress,ACCEL_XOUT_H,Acc);
            GetData(SlaveAddress,GYRO_XOUT_H,Gyro);    
           
    gd_led_toggle();
}

}

void nvic_config(void)
{

nvic_irq_enable(TIMER2_IRQn, 0, 0);

}

void timer_config(void)
{

TIMER2 Configuration:
TIMER2CLK = SystemCoreClock/8400(GD32F330)or 10800(GD32F350) = 10KHz.
the period is 1s(10000/10000 = 1s).

timer_oc_parameter_struct timer_ocinitpara;
timer_parameter_struct timer_initpara;

/* enable the peripherals clock */
rcu_periph_clock_enable(RCU_TIMER2);

/* deinit a TIMER */
timer_deinit(TIMER2);
/* initialize TIMER init parameter struct */
timer_struct_para_init(&timer_initpara);
/* TIMER2 configuration */


timer_initpara.prescaler         = 4999;
timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection  = TIMER_COUNTER_UP;
timer_initpara.period            = 999;
timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
timer_init(TIMER2, &timer_initpara);

/* clear channel 0 interrupt bit */
timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_UP);
/* enable the TIMER interrupt */
timer_interrupt_enable(TIMER2, TIMER_INT_UP);
/* enable a TIMER */
timer_enable(TIMER2);

}

int main(void)
{

gd_led_config();
systick_config();

 
i2c0_gpio_config();

i2c_config();

mpu6050_init();

LCD_Init();
LCD_Fill(0,0,LCD_W,LCD_H,BLACK);
//LCD_ShowString(0,0,"Hellow GD32F310G8!",WHITE,BLUE,12,0);

  
timer_config();
/* configure the TIMER2 interrupt */
nvic_config();



while(1) {
  
  
  
  
   
                        
                   
          for(int i=0;i<128;i++){
           LCD_DrawPoint( i, data[i],RED);
           LCD_DrawPoint( i, data2[i],GREEN);
           LCD_DrawPoint( i, data3[i],BLUE);
             }
          delay_1ms(10);

         for(int i=0;i<128;i++){
          LCD_DrawPoint( i, data[i],BLACK);
          LCD_DrawPoint( i, data2[i],BLACK);
          LCD_DrawPoint( i, data3[i],BLACK);
          }
 
         for(int i=0;i<127;i++){
          data[i]=data[i+1];
          data2[i]=data2[i+1];
         data3[i]=data3[i+1];
 }

 data[127]=20+(int)(((float)Gyro[0])/164);
 data2[127]=60+(int)(((float)Gyro[1])/164);
 data3[127]=100+(int)(((float)Gyro[2])/164);
                
 
  
 
 
  //char cpd[10];
   //sprintf(cpd,"%d",Acc[0]);
   
   //LCD_ShowString(0,0,cpd,WHITE,BLUE,12,0);

 

}

}

void gd_led_config(void)
{

rcu_periph_clock_enable(RCU_GPIOA);


gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);

GPIO_BC(GPIOA) = GPIO_PIN_1;

}

void gd_led_toggle(void)
{

GPIO_TG(GPIOA) = GPIO_PIN_1;

}

3.效果

IMG_20220427_112625.jpg

GD32存在一个问题,用队列缓冲陀螺仪数据时,运行数秒后死机。

推荐阅读
关注数
10694
内容数
187
中国高性能通用微控制器领域的领跑者兆易创新GD系列芯片技术专栏。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息