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
{
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);
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);
LCD_WR_DATA8(0x1A);
LCD_WR_REG(0x36);
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);
LCD_WR_REG(0x3A);
LCD_WR_DATA8(0x05);
LCD_WR_REG(0x29);
}
显示函数:
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
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)){
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;
rcu_periph_clock_enable(RCU_TIMER2);
timer_deinit(TIMER2);
timer_struct_para_init(&timer_initpara);
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);
timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_UP);
timer_interrupt_enable(TIMER2, TIMER_INT_UP);
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);
timer_config();
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);
}
}
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.效果
GD32存在一个问题,用队列缓冲陀螺仪数据时,运行数秒后死机。
原作者:兆易创新GD32 MCU zhai