我要成为嵌入式高手之4月15日ARM第八天!!
————————————————————————————
ADC
概念
ADC是模拟到数字转换器的缩写。是一种电子设备或者模块。用于将连续变化的模拟信号转换为离散的数字信号,以便数字系统能够对其进行处理和分析。
模拟量和数字量的特点
模拟信号一般是指连续变化的电压信号,其数值在一定范围内变化。而数字信号是由一系列离散的数字表示,只能取有限的值,通常以二进制的形式表示。
ADC的分辨率
逐次逼近法比较的次数决定了测量的精度,这个精度称为ADC的分辨率
ADC的转换原理
ADC的工作原理是将模拟信号分割成一系列离散的取样,并将每个取样值转换为相应的数字表示
涉及到两个步骤:
1、采样:ADC将连续变化的模拟信号在一定时间间隔进行取样。取样频率决定了每秒采集到的样本数,通常以Hz表示;采样过程 通过保持并测量模拟信号在每个采样时间点的电压值来实现。
2、量化:采样得到的连续模拟信号经过量化转换为数字形式。量化是将每个采样值映射到一个离散的数字值的过程。通常通过比较采样值与参考电压之间的差异,并将其转换为数字表示。
模/数转换器及触摸屏接口
10 位 CMOS ADC(模/数转换器)是一个 8 通道模拟输入的再循环类型设备。
特性
– 分辨率:10 位
– 差分线性误差:± 1.0 LSB
– 积分线性误差:± 2.0 LSB
– 最大转换率:500 KSPS
– 功耗低
– 供电电压:3.3V
– 模拟输入范围:0 至 3.3V
– 片上采样-保持功能
– 普通转换模式
– 分离的 X/Y 方向转换模式
– 自动(顺序)X/Y 方向转换模式
– 等待中断模式
A/D 转换时间
当 PCLK 频率在 50MHz 并且预分频器的值为 49 时,共 10 位的转换时间如下:
A/D 转换器频率 = 50MHz / (49+1) = 1MHz
转换时间 = 1/(1MHz / 5 周期) = 1/200KHz = 5µs
ADC 和触摸屏接口特殊寄存器
ADC 控制寄存器(ADCCON)
ADC 转换数据寄存器(ADCDAT0)
用串口调试
void adc_init(void)
{ADCCON |= (1 << 14);ADCCON &= ~(0xFF << 6);ADCCON |= (49 << 6);ADCCON &= ~(7 << 3);ADCCON &= ~(1 << 2);ADCCON &= ~(1 << 1);
}unsigned short do_adc(void)
{ADCCON |= (1 << 0);while ((ADCCON & (1 << 15)) == 0);//结束的结果放在ADCDAT0寄存器return ADCDAT0 & 0x3FF;
}
#include "clock.h"
#include "led.h"
#include "adc.h"
#include "uart.h"
#include <stdio.h>
#include <string.h>int main(void)
{unsigned short ret; char s[32];clock_init();adc_init();uart0_init(); while (1){ret = do_adc();sprintf(s, "%u", ret);uart0_send_buffer((unsigned char *)s, strlen(s));delay(0x3FFFF);}
}
ADC 控制寄存器(ADCCON)的读启动A/D转换:只要读走数据,下次就立马启动转换
解决误差
1、硬件加入滤波
2、软件采集时连续采集多个点,然后均值滤波、最小二乘法等算法进行求值
IIC(I2C)
概念:
中文叫集成电路总线。是一种同步串行半双工通信总线方式。所有挂载在IIC总线上的设备都有两根信号线,一根是数据线SDA,另一根是时钟线SCL。这两个信号都是双向的。
时序逻辑:
1、IIC总线规定,设备在空闲时,两根总线都处于高电平状态。为保证这种状态,数据线SDA和时钟线SCL都要 外接上拉电阻。
2、每次通信前,发送方先发送一个“起始信号”(SCL为高电平时,SDA发送一个低电平);当其他设备接收到这个起始信号后,将进行一次“总线仲裁”(除了发送起始信号以外的其他设备都处于聆听状态)
3、数据传输时,时钟线 SCL 上的信号为高电平期间,数据线 SDA 上的数据必须保持稳定;时钟线SCL为低电平时,数据线SDA上的电平才允许变化;SCL信号由发送端提供。输出到数据线SDA上的每个字节必须是八位;数据传输时先传输最高位MSB,后传输最低位LSB。
4、发送端每发送一个字节,就在时钟脉冲9期间释放数据线SDA,由接收器反馈应答信号:主机SCL拉高,读取从机SDA的电平。有效应答位ACK:接收器在第9个时钟脉冲之前的低电平期间将数据线SDA拉低,并且确保在该时钟的高电平期间为稳定的低电平。
SDA低电平:规定为有效应答位(ACK),表示接收器成功接收该字节。
SDA为高电平:规定为非应答位(NACK),表示接受器没有成功接收该字节。
5、发送方发送完最后一个bit后,需要发送一个结束标志位:SCL为高电平时,数据线SDA由低向高跳变。
一个板子最多装载8块AT24C08(A0,A1,A2组合)
时序图
1、字节写
START:2440
2、页写
3、当前地址读
5、随机读
6、连续读
2440内部IIC寄存器
S3C2440A RISC(经典指令集) 微处理器可以支持一个多主控 IIC 总线串行接口。一条专用串行数据线(SDA)和一条专用 串行时钟线(SCL)传递连接到 IIC 总线的总线主控和外设之间的信息。SDA 和 SCL 线都为双向的。
S3C2440A 的 IIC 总线接口有 4 种工作模式:
1、主机发送模式 2、主机接收模式 3、从机发送模式 4、从机接收模式
1、主机发送模式
端口 E 控制寄存器(GPECON,GPEDAT,GPEUP)
多主机 IIC 总线控制(IICCON)寄存器
IIC总线应答使能置1:当2440往24c02写数据时,24c02发送应答信号时,2440会产生中断
发送时钟值不:能超过400k
中断模式(INTMOD)寄存器
中断屏蔽(INTMSK)寄存器
中断偏移(INTOFFSET)寄存器
初始化函数:
void iic_init(void)
{GPECON |= (2 << 28) | ((unsigned int)2 << 30);IICCON |= (1 << 7) | (1 << 6) | (1 << 5);IICCON &= ~(0x0F << 0); INTMOD &= ~(1 << 27);INTMSK &= ~(1 << 27);
}unsigned int iic_isr;void iic_handle(void)
{iic_isr = 1;
}void do_wait_ack(void)
{iic_isr = 0;IICCON &= ~(1 << 4);while (iic_isr == 0){delay(0x4000);}
}
1、主机发送函数
void write_24c02(unsigned char address, unsigned char *pdata, unsigned int len)
{IICSTAT = 0xF0;IICDS = 0xA0;//24c02地址do_wait_ack();IICDS = address;//24C02内部数据将要存储的地址do_wait_ack();while (len != 0){IICDS = *pdata++;do_wait_ack();--len; }IICSTAT = 0x0D;IICCON &= ~(1 << 4);delay(0x4000);
}
2、主机接收模式
主机接收函数:
void read_24c02(unsigned char address, unsigned char *pdata, unsigned int len)
{unsigned int i;IICCON |= (1 << 7);IICSTAT = 0xF0;IICDS = 0xA0;//24c02地址do_wait_ack();IICDS = address;do_wait_ack();IICSTAT = 0xB0;IICDS = 0xA0;do_wait_ack();*pdata = IICDS;do_wait_ack();for (i = 0; i < len; ++i){if (i == len - 1){IICCON &= ~(1 << 7);*pdata++ = IICDS;IICCON &= ~(1 << 4);delay(0x4000);}else{*pdata++ = IICDS;do_wait_ack();}}IICSTAT = 0x90;IICCON &= ~(1 << 4);delay(0x4000);
}
main.c
int main(void)
{char s[128] = {0};wdt_init();clock_init();uart0_init();eint_init();iic_init();pos = 0;write_24c02(0, "hello world", strlen("hello world"));read_24c02(0, (unsigned char *)s, 15); //uart0_send_buffer((unsigned char *)s, 15);while (1){if (pos != 0){delay(0x3FFFF);write_24c02(0, rcvBuffer, pos);delay(0x3FFF);read_24c02(0, (unsigned char *)s, pos);uart0_send_buffer((unsigned char *)s, pos);pos = 0; }}
}
此外还应该打开中断和串口进行调试