【1】UART实验
实验目的:通过串口进行收发数据
一、看原理图
发现UART接在CPU的GPA1_0和GPA1_1引脚
二、看芯片手册
GPA1CON:
GPA1CON[1] [7:4]: 0x2 = UART_2_TXD //UART的发送数据功能
GPA1CON[0] [3:0]: 0x2 = UART_2_RXD //UART的接收数据的功能
UART所支持的通信协议:
1个起始位
5-8个数据位
0/1奇偶校验位
1-2个停止位
可编程的波特率
我们常用的协议:8N1
1个起始位和1个停止位 8个数据位 没有奇偶校验位 115200
ULCONn:
0x3 //选择8N1的协议
UCONn
Transmit Mode [3:2]: 01 = Interrupt request or polling mode //我们用轮询模式(polling)
Receive Mode [1:0]: 01 = Interrupt request or polling mode
UTRSTATn
Transmit buffer empty [1]: 0 = Buffer is not empty //等待
1 = Buffer is empty //可以发送
Receive buffer data ready [0]: 0 = Buffer is empty //等待
1 = Buffer has a received data //可以读
UTXHn
UTXHn [7:0] RWX Transmits data for UARTn //发送数据
URXHn
URXHn [7:0] R Receives data for UARTn //接收数据
UBRDIVn
UBRDIVn [15:0]: 53
UFRACVALn
UFRACVALn [3:0]: 5
For example, if the Baud rate is 115200 bps and SCLK_UART is 40 MHz, UBRDIVn and UFRACVALn are:
DIV_VAL = (40000000/(115200*16))-1
= 21.7 – 1
= 20.7
UBRDIVn = 20 (integer part of DIV_VAL)
UFRACVALn/16 = 0.7
DIV_VAL = (100000000/(115200*16))-1
= 53.3
UBRDIVn = 53 (integer part of DIV_VAL)
UFRACVALn/16 = 0.3
UFRACVALn = 5
【1.2】RTC
RTCCON
CTLEN [0]: 0 = Disables RTC control
1 = Enables RTC control
BCDSEC
BCDSEC = 0x30
【2】ADC
实验目的:测量电位器两段的电压,进行转化
ADCCON
RES [16]:1 = 12bit A/D conversion //12位的转化精度
ECFLG [15]: 0 = A/D conversion in process //判断AD转化是否结束的标记
1 = End of A/D conversion
PRSCEN [14]: A/D converter prescaler enable 1 = Enable
PRSCVL [13:6]:0xff
STANDBY [2]: 0 = Normal operation mode
READ_ START [1]: A/D conversion start by read //读一次就开始转化一次
0 = Disables start by read operation
1 = Enables start by read operation
ENABLE_ST ART [0]:1 = A/D conversion starts and this bit is automatically cleared after the start-up.
//使能一次,ADC就开始转化一次
ADCDAT
DATA [11:0] R ADC conversion data value Data value: 0x0 ~ 0xFFF
ADCMUX
SEL_MUX [3:0] : 0011 = AIN 3
I2C
1. 概念,IIC是由PHILIPS公司推出的两线式串行总线,通过串行数据线(SDA)和串行时钟线(SCL)在连接到总线上的设备间进行
传递消息,每一个设备都有自己唯一的地址识别
2. 看原理图,找到从机设备(三轴加速度传感器)所接的IIC引脚 -- I2C_SCL5 I2C_SDA5
配置相关引脚为IIC功能 -- XspiMISO0/I2C_5_SDA/GPB_2 XspiMOSI0/I2C_5_SCL/GPB_3
1. GPBCON
GPBCON[2] [11:8]:0x3 = I2C_5_SDA
GPBCON[3] [15:12]:0x3 = I2C_5_SCL
2. GPBPUD
GPBPUD[n] [2n + 1:2n]:0x0 = Disables Pull-up/Pull-down
3. 看芯片手册上的IIC概述
1. 当IIC被闲置的时候,SDA和SCL都处于高电平,在SCL处于高电平的时候,SDA的一个下降沿表示一个start信号
SDA的一个上升沿表示一个stop信号
2. 我们的start和stop信号都是有主机设备产生的
3. 主机发送start信号后接着通过SDA发送一个7bits的地址,这个地址决定主机要通信的从机设备,第八位决定主机是要读
从机设备还是写从机设备
从SDA发送的数据只能是八位八位的,在接收到一个字节后会立马发出一个响应信号(ACK)
主机通过判断中断挂起位来判断是否接受到数据或者ACK应答信号
4. IIC的四种操作模式
主机发送、主机接收、从机发送、从机接收
5. 分析时序图
6. 寄存器 - 看原理图发现我们的三轴加速度传感器接I2C_SCL5
1. I2CCON5
Acknowledge generation [7]: 1 = Enables
In Tx mode, the I2CSDA is idle in the ACK time.
In Rx mode, the I2CSDA is low in the ACK time
注意: ACK generation is disabled before Reading the last data to generate the STOP condition in Rx mode.
Tx clock source selection [6]: 0 = I2CCLK = fPCLK/16
1 = I2CCLK = fPCLK/512
Tx/Rx Interrupt (5) [5]: 1 = Enables
Interrupt pending flag [4]: 0 = 1) No interrupt is pending (If Read). //没有收到ACK
2) Clears pending condition and resumes the operation (if Write).
1 = 1) Interrupt is pending (If Read) //接收到ACK
2) N/A (If Write)
Transmit clock value (4) [3:0]: Tx clock = I2CCLK/(I2CCON[3:0] + 1)
2. I2CSTAT5
Mode selection [7:6]: 00 = Slave receive mode
01 = Slave transmit mode
10 = Master receive mode
11 = Master transmit mode
Busy signal status/START STOP condition [5]: 0 = (Read) Not busy (If Read)
(write) STOP signal generation
1 = (Read) Busy (If Read)
(write) START signal generation.
Transfers the data in I2CDS automatically just after the start signal.
Serial output [4]: 1 = Enables Rx/Tx
Last-received bit status flag [0]:1 = Last-received bit is set to 1 (does not receive ACK).
3. I2CADD5 //用来读从机地址的
Slave address [7:0]: Slave address: [7:1]
4. I2CDS5
Data shift [7:0]: 8-bit data shift register for I2C-bus Tx/Rx operation
4. 看MPU6050的数据手册(Datasheet)
1. The slave address of the MPU-60X0 is b110100X which is 7 bits long. The LSB bit of the 7 bit address is
determined by the logic level on pin AD0
经查看三轴加速度的原理图发现AD0为0,所以从机地址是0x68 ==》 slave_addr = 0x68
2. To read the internal MPU-60X0 registers, the master sends a start condition, followed by the IIC address and
a write bit, and then the register address that is going to be read
当要对MPU6050内部的寄存器进行操作时,在发送完IIC从机地址收到ACk后还要接着发送6050内部寄存器地址
2. 分析主发从(MPU6050)收的时序
5. 查看MPU6050的寄存器手册(Register Map) 寄存器都是8位的
SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz)
CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz)
GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x18(不自检,2G,5Hz)
GYRO_ZOUT_H 0x47 //获取MPU6050-Z轴角速度高字节
GYRO_ZOUT_L 0x48 //获取MPU6050-Z轴角速度低字节
PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用) 用来设置6050内部时钟
6. 写程序
iic_init
/* 1. 初始化GPIO引脚为IIC相关功能 */
GPBCON = GPBCON & (~(0xf<<8)) | (0x3<<8); //配置GPB_2引脚为IIC_SDA
GPBCON = GPBCON & (~(0xf<<12)) | (0x3<<12); //配置GPB_3引脚为IIC_SCL
/* 2. 设置IIC的工作时钟,使能IIC中断,使能ACK */
I2CCON5 |= (0x7<<5);
/* 3. 使能IIC串口输出 */
I2CSTAT5 |= (1<<4);
/*********************************************************************************************************/
iic_write -- 参数:addr_slave(从机地址) addr_slave_reg(从机寄存器地址) data
/* 1. 发送start信号 */
I2CSTAT5 |= (1<<5);
/* 2. 设置主发模式 */
I2CSTAT5 |= (3<<6);
/* 3. 发送IIC从机设备地址 */
I2CDS5 = (0x68<<1);
while(!(I2CCON5 & (1<<4))); //等待,直到中断被挂起(收到ACK)
/* 4. 发送从设备内部寄存器地址,发送后先清中断挂起(从新开始发送),然后再等待中断被挂起(收到ACK) */
I2CDS5 = addr_slave_reg;
I2CCON5 &= ~(1<<4); //清中断挂起位
while(!(I2CCON5 & (1<<4))); //等待,直到中断被挂起(收到ACK)
/* 5. 发送数据,发送前先等待中断被挂起(收到ACK),然后清中断挂起,最后再发送 */
I2CDS5 = data;
I2CCON5 &= ~(1<<4);
while(!(I2CCON5 & (1<<4)));
/* 6. 发送stop信号,禁止接受ACK */
I2CSTAT5 = 0xd0;
/* 请中断挂起 */
I2CCON5 &= ~(1<<4);
delay_ms(10);
/*********************************************************************************************************/
iic_read -- 参数:addr_slave(从机地址) addr_slave_reg(从机寄存器地址)
/* 1. 发送start信号 */
I2CSTAT5 |= (1<<5)|(1<<4);
/* 2. 设置主发模式 */
I2CSTAT5 |= (3<<6);
/* 3. 发送IIC从机设备地址+写0 */
I2CDS5 = (0x68<<1);
while(!(I2CCON5 & (1<<4))); //等待,直到中断被挂起(收到ACK)
/* 4. 发送从设备内部寄存器地址,发送后先清中断挂起(从新开始发送),然后再等待中断被挂起(收到ACK) */
I2CDS5 = addr_slave_reg;
I2CCON5 &= ~(1<<4); //清中断挂起位
while(!(I2CCON5 & (1<<4))); //等待,直到中断被挂起(收到ACK)
/* 5. 清中断,发stop信号 */
I2CCON5 &= ~(1<<4);
I2CSTAT5 = 0xd0;
/* 6. 设置主机接收模式 */
I2CSTAT5 = I2CSTAT5& (~(3<<6)) | (2<<6);
/* 7. 发送start信号,发从机地址+读1位 */
I2CSTAT5 |= (1<<5);
I2CDS5 = (0x68<<1) | 0x1;
while(!(I2CCON5 & (1<<4)));
/* 5. 发送数据,发送前先等待中断被挂起(收到ACK),然后清中断挂起,最后再发送 */
I2CDS5 = data;
I2CCON5 &= ~(1<<4);
while(!(I2CCON5 & (1<<4)));
/* 6. 发送stop信号 */
I2CSTAT5 = 0xd0;
/* 清中断挂起位 */
I2CCON5 &= ~(1<<4);
delay_ms(10);
/*********************************************************************************************************/
init_mpu6050
iic_write(SlaveAddress, PWR_MGMT_1, 0x00); //设置使用内部时钟8M
iic_write(SlaveAddress, SMPLRT_DIV, 0x07); //设置陀螺仪采样率
iic_write(SlaveAddress, CONFIG, 0x06); //设置数字低通滤波器
iic_write(SlaveAddress, GYRO_CONFIG, 0x18); //设置陀螺仪量程+-2000度/s
iic_write(SlaveAddress, ACCEL_CONFIG, 0x0); //设置加速度量程+-2g
最后一步,在main中读Z轴的加速度
zvalue_h = iic_read(SlaveAddress, GYRO_ZOUT_H); //获取MPU6050-Z轴角速度高字节
zvalue_l = iic_read(SlaveAddress, GYRO_ZOUT_L); //获取MPU6050-Z轴角速度低字节
zvalue = (zvalue_h<<8)|zvalue_l; //获取MPU6050-Z轴角速度