最近真的很忙,不是借口什么的,很想回答学校,再好好学习一遍,自己下班后(虽然我们没有加班)但是回去还得看看自己没有完成的东西,还得学习ARM,模电电路还要拿出来看看,信号系统,高频等一大推书看看。上学的时候没有真正好好的学习,现在后悔了,自己补啊~~~如果还在学校上学的同学,每一门课都是真的很重要,不要说没有用,等你要用到的时候,你才发现自己,学的太少,最近搞无线,比较累,又想到自己上学的时候电磁场与电磁波不好好学,现在找不到原因~~~ 呵呵,题外话,在上大学的同学好好学习,过了大学,你真的发现大学真的很美好~~~很美好~~~很怀念~~~
言归正传~~~讲讲我自己学习ARM的一些经验吧,个人经验只做参考,有错误的地方还请高手指正~~~谢谢~~~
关于UART 是什么? 1 . UART 简介 计算机与外部设备的连接,基本上使用了两类接口:串行接口与并行接口。并行接口是 指数据的各个位同时进行传送,其特点是传输速度块,但当传输距离远、位数又多时,通信 线路变复杂且成本提高。串行通信是指数据一位位地顺序传送,其特点是适合于远距离通信, 通信线路简单,只要一对传输线就可以实现双向通信,从而大大降低了成本。 串行通信又分为异步与同步两类。UART(Universal Asyn chro nous Receiv er/Transm itter , 通用异步收发器)正是设备间进行异步通信的关键模块。它的重要作用如下所示: 2 处理数据总路线和串行口之间的串/ 并、并/ 串转换; 3 通信双方只要采用相同的帧格式和波特率,就能在未共享时钟信号的情况下,仅用 两根信号线(Rx和Tx)就可以完成通信过程; 4 采用异步方式,数据收发完毕后,可通过中断或置位标志位的方式通知微控制器进 行处理,大大提高微控制器的工作效率。 若加入一个合适的电平转换器,如SP323 2E、SP3485,UART 还能用于RS-232、RS-485 通信,或与计算机的端口连接。UART 应用非常广泛,手机、工业控制、PC等应用中都要 用到UART 。 这个是UART 的基本简介,想要更全的,请Google。 下面我们看下ARM的UART 中有什么? 1 :Programmable baud-rate generator allowing speeds up to 5 Mbps for regular speed (divide by 16) and 10 Mbps for high speed (divide by 8) 2:FIFO trigger levels of 1/8, 1/4, 1/2, 3/4, and 7/8。 3:IrDA serial-IR (SIR) encoder/decoder providing 我关注这个三个东西,觉得很重要,其它的和基本的UART的没有什么差别,尤其最后的串行红外编码,以前在MSP430的F5系列上面用过确实不错。 关于更多的UART 通信的问题,大家可以参看数据手册,有中文的,也有英文的。 下面用个程序 来说明UART 通信问题: void uartInit(void) { SysCtlPeriEnable(SYSCTL_PERIPH_UART2); // 使能UART模块 SysCtlPeriEnable(SYSCTL_PERIPH_GPIOG); // 使能RX/TX所在的GPIO端口 GPIOPinTypeUART(GPIO_PORTG_BASE, // 配置RX/TX所在管脚为 GPIO_PIN_0 | GPIO_PIN_1); // UART收发功能 UARTConfigSet(UART2_BASE, // 配置UART端口 9600, // 波特率:9600 UART_CONFIG_WLEN_8 | // 数据位:8 UART_CONFIG_STOP_ONE | // 停止位:1 UART_CONFIG_PAR_NONE); // 校验位:无 UARTFIFOLevelSet(UART2_BASE, // 设置收发FIFO中断触发深度 UART_FIFO_TX2_8, // 发送FIFO为2/8深度(4B) UART_FIFO_RX6_8); // 接收FIFO为6/8深度(12B) UARTIntEnable(UART2_BASE, UART_INT_TX); // 使能发送中断 IntEnable(INT_UART2); // 使能UART总中断 IntMasterEnable(); // 使能处理器中断 UARTEnable(UART2_BASE); // 使能UART端 } // 通过UART发送字符串 void uartPuts(const char *s) { while (*s != '\0') { UARTCharPut(UART2_BASE, *(s++)); } } // 定义发送中断标志,如果出现发送中断,则置位TxIntFlag volatile tBoolean TxIntFlag = false; // 主函数(程序入口) int main(void) { clockInit(); // 时钟初始化:晶振,6MHz uartInit(); // UART初始化 for (;;) { uartPuts("0123456789ABCDEF"); // 一次性填满FIFO SysCtlDelay(11 * (TheSysClock / 3000)); // 延迟11ms以内不会产生中断 // 延迟12ms以上就会产生中断 if (TxIntFlag) { TxIntFlag = false; // 在这里设置观察断点 } } } // UART2中断服务函数 void UART2_ISR(void) { unsigned long ulStatus; ulStatus = UARTIntStatus(UART2_BASE, true); // 读取当前中断状态 UARTIntClear(UART2_BASE, ulStatus); // 清除中断状态 if (ulStatus & UART_INT_TX) // 若是发送中断 { TxIntFlag = true; } } 对照程序,可以理解下UART通信的过程。 初始化,然后发送数据,然后选择中断的深度或者叫发送的深度,FIFO的深度,这样就可以了,关于接收其实也是一样,我自己搞了一个FIFO 发送和接收的程序,后来不知道怎么被我给删了,自己都无语了。
其实在我之前做UART的时候,用的是定时器模拟的,那样更能理解UART的通信问题,了解UART 的原理,以及发送过程中是什么样子的,再来了解这个应该是非常简单的。 如果有兴趣的同学建议看下MSP430里面用定时器模拟UART ,这样就应该能很清楚了解UART的底层协议~~~。 在这里我还想说下,搞ARM由于我是从单片机转过来的,所以我更关心寄存器怎么操作的。 硬件寄存器的操作: 访问片内外设的库函数最终都是由在头文件“hw_types .h ” 里定义的3 个硬件寄存器访问宏函数HWREG( )、HWREGH( )、HWREGB ( )实现的。这3个宏函数在定义的时候被声明为volatile 属性的指针,所以这种访问不会被编译器优化掉, 即每次读取时都返回硬件寄存器的当前值、每次写入时都会把最新的数值写入硬件寄存器。 举个例子: #define SYSCTL_BASE 0x400FE000 // 定义系统控制模块的基址 #define RCGC 2 (SYSCTL_BASE + 0x108) // 定义时钟选通控制寄存器2 // 主函数(程序入口) int ma in(voi d) { clockIni t ( ); // 时钟初始化:晶振,6MHz HWREG(RCGC2) |= 0x00000002; // 选通GPIOB 模块的时钟 While(1); } 如果有兴趣的同学可以查看userguide 对照下,肯定是选通定时器的时钟模块。 如果想要修改BIT的话,也是有函数的HWREGBITW( ) HWREGBITH( ) HWREGBITB( ) 这三个函数为别为whole bit(0-32), High bit(0-15) , bit(15)后面的数字指的是BIT 用一个程序来解释怎么操作的。 int main(voi d) {
clockInit ( ); // 时钟初始化:晶振,6MHz HWREGBITW(RCGC2, 1) = 1; // 选通GPIOB 模块的时钟 While(1); } 同样也是选通GPIOB 模块的时钟 。 这个就是说的BIT——band 位操作,这样我们就能很清楚驱动库里面的寄存器怎么设置的,然后你就可以改了。因为底层的东西你了解清楚之后,这样你就可以随心所欲的用它了。 写的比较乱,大家凑合着看看,这个心得已经没有加图片了,因为已经没有必要了,因为不可能把每步都贴出来,更多还是要自己理解,我也是自己一步一步的来学ARM,有什么不对的地方还望大家指正
谢谢~~~
|