我要成为嵌入式高手之4月15日ARM第八天!!
————————————————————————————
定时器
S3C2440A 有 5 个 16 位定时器。其中定时器 0、1、2 和 3 具有脉宽调制(PWM)功能。定时器 4 是一个无 输出引脚的内部定时器。定时器 0 还包含用于大电流驱动的死区发生器。
使用s3c2440的时钟4实现1毫秒的定时
定时器配制寄存器 0(TCFG0)
预分频寄存器
定时器配制寄存器 1(TCFG1)
分频寄存器
定时器输入时钟频率 = PCLK / {预分频值+1} / {分频值}
{预分频值} = 0~255
{分频值} = 2, 4, 8, 16
定时器控制寄存器 1(TCON)
定时器 4 计数缓冲寄存器(TCNTB4)
对算出来的计数器值(2500)的备份
定时器 4 计数监视寄存器(TCNTO4)
很少用到
设置中断寄存器INTMOD、INTMSK
将中断寄存器设置为定时器4
void timer4_init(void)
{TCFG0 |= (19 << 8);//预分频值为4//TCFG1 |= (1 << 16);//分频值为4TCON |= (1 << 22);TCNTB4 = 2500;//设置计数的值TCON |= (1 << 21);TCON &= ~(1 << 21);//先置1再置0将计数值修改进去//打开中断INTMOD &= ~(1 << 14);INTMSK &= ~(1 << 14);TCON |= (1 << 20);//打开定时器
}
PWM定时器
多出一个比较寄存器,相当于 TCNTB 控制周期,TCMPB控制占空比
在此用蜂鸣器调制PWM
用GPB0实现周期400hz,占空比50%的方波
参数设置与定时器4差不多
此外还需要设置蜂鸣器GPIO
端口 B 控制寄存器(GPBCON)
int counter0 = 0;void timer0_init(void)
{//设置蜂鸣器GPIOGPBCON |= (2 << 0);TCFG0 |= (9 << 0);//预分频值为10 = 5MTCFG1 |= (1 << 0);//分频值为4 = 1.25MTCON |= (1 << 22);TCNTB0 = 3125;//设置计数的值 = 400HZTCNTB0 = 3125 / 2;//设置占空比为50%TCON |= (1 << 3) | (1 << 2);//(1 << 2)由高电平开始TCON |= (1 << 1);TCON &= ~(1 << 1);//先置1再置0将计数值修改进去//打开中断INTMOD &= ~(1 << 10);INTMSK &= ~(1 << 10);TCON |= (1 << 0);//打开定时器
}int timer0_handle(void)
{++counter0;if (counter0 >= 1000){ledAllNor();counter0 = 0;}
}
UART串口通信
S3C2440A 的每个 UART 包括 7 种状态(Tx/Rx/错误)信号:溢出错误、奇偶校验错误、帧错误、断点、接收 缓冲器数据就绪、发送缓冲器空以及发送移位器空,全部都由相应 UART 状态寄存器(UTRSTATn/UERSTATn) 标示。
我们主要用到接收缓冲区数据中断
外设总线:APB
要发送的数据先写入发送缓冲区,然后通过发送移位器一个字节一个字节发;接收亦如此
UART 方框图(带 FIFO)
波特率时钟是通过 16 和由 UART 波特率分频寄存器(UBRDIVn)指定的 16 位分频系数来分频源时钟(PCLK,FCLK/n 或 UEXTCLK)产生的。 UBRDIVn 由下列表达式决定:
UBRDIVn = (int)( UART 时钟 / ( 波特率 × 16) ) - 1
端口 H 控制寄存器(GPHCON,GPHDAT,GPHUP)
在此要将GPH2和GPH3设置为串口 发送 / 接收 模式
UART 线路控制寄存器(ULCON)
UART 控制寄存器(UCON)
在此不用管FCLK,选择PCLK
Tx发送中断类型:缓冲区一变成空,就产生中断
Rx接收中断类型:设置为脉冲类型
……
UART TX/RX 状态寄存器
用来查询的
UART 发送缓冲寄存器(保持寄存器和 FIFO 寄存器)
发送数据时进行修改
UART 接收缓冲寄存器(保持寄存器和 FIFO 寄存器)
UART 波特率分频寄存器
要进行计算得出波特率
波特率时钟是通过 16 和由 UART 波特率分频寄存器(UBRDIVn)指定的 16 位分频系数来分频源时钟(PCLK,FCLK/n 或 UEXTCLK)产生的。 UBRDIVn 由下列表达式决定:
UBRDIVn = (int)( UART 时钟 / ( 波特率 × 16) ) - 1
例如,如果波特率为 115200 bps 并且 UART 时钟为 40 MHz,UBRDIVn 为:
UBRDIVn = (int)(40000000 / (115200 x 16) ) - 1
= (int)(21.7) - 1 [取最接近的整数]
= 22 - 1 = 2
void uart0_init(void)
{unsigned int t;GPHCON |= (2 << 4) | (2 << 6);t = ULCON0;t &= ~(1 << 6);t &= ~(7 << 3);t &= ~(1 << 2);t |= (3 << 0);ULCON0 = t;t = UCON0;t &= ~(3 << 10);t &= ~((1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4));t |= (1 << 2) | (1 << 0);UCON0 = t;UBRDIV0 = 325;
}
发送一个字符:
void uart0_send_char(unsigned char data)
{UTXH0 = data;while ((UTRSTAT0 & (1 << 1)) == 0);//查询TX寄存器是否为0,为0表示发送完毕,非0表示还在发送,需要等待发送完毕
}
发送字符串:
void uart0_send_buffer(unsigned char *p, unsigned int len)
{int i = 0;for (i = 0; i < len; ++i){uart0_send_char(*p++); }
}
数据接收
首先需要打开中断
中断模式(INTMOD)寄存器
中断屏蔽(INTMSK)寄存器
次级源挂起(SUBSRCPND)寄存器
中断次级屏蔽(INTSUBMSK)寄存器
对于接收放需要打开INT_RXD0
中断偏移(INTOFFSET)寄存器
接收到的数据要从接收缓存区读取
UART 接收缓冲寄存器(保持寄存器和 FIFO 寄存器)
void uart0_init(void)
{unsigned int t;//将GPIO端口设置为串口GPHCON |= (2 << 4) | (2 << 6);//设置串口线路控制寄存器t = ULCON0;t &= ~(1 << 6);t &= ~(7 << 3);t &= ~(1 << 2);t |= (3 << 0);ULCON0 = t;//设置控制寄存器t = UCON0;t &= ~(3 << 10);t &= ~((1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4));t |= (1 << 2) | (1 << 0);UCON0 = t;//设置波特率UBRDIV0 = 325;//设置中断INTMOD &= ~(1 << 28);INTMSK &= ~(1 << 28);INTSUBMSK &= ~(1 << 0);
}
unsigned char rcvBuffer[256];
unsigned int pos;void uart0_handle(void)
{if ((SUBSRCPND & (1 << 0)) != 0){rcvBuffer[pos++] = URXH0; }SUBSRCPND = SUBSRCPND;
}
main.c
int main(void)
{ wdt_init();clock_init();led_init();uart0_init(); pos = 0;while (1){if (pos != 0){delay(0x3FFFF);uart0_send_buffer(rcvBuffer, pos);pos = 0;}}
}