1. UART
1.1 定义
UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)是一种用于串行通信的硬件设备或模块。它的主要功能是将数据在串行和并行格式之间进行转换。UART通常用于计算机与外围设备或嵌入式系统之间的数据传输。
1.2 特点
-
异步通信:UART不需要发送和接收设备之间的时钟信号同步,数据传输速率和传输格式(如起始位、数据位、校验位、停止位)在通信双方事先协商好。
-
全双工通信:UART可以同时进行数据的发送和接收。
-
串行数据传输:数据一位一位地传输,减少了连线数量,但需要更多的时间来传输数据。
-
组成部分:
- 发送器(Transmitter):将并行数据转换为串行数据并发送出去。
- 接收器(Receiver):接收串行数据并将其转换为并行数据。
1.3 代码
#include <s3c2440.h>
#include <string.h>
#include <stdio.h>
#include "led.h"
#include "key.h"
#include "interrupt.h"
#include "delay.h"
#include "pwm.h"
#define ADDRESS 0X08
void init_wdt(void) //初始化看门狗,禁止启动,关闭看门狗
{
WTCON &= ~(1 << 0);
}
void init_clk(void)
{
unsigned int t = MPLLCON; //将PCLK频率存入变量设置好再进行修改,防止频率修改中途器件因为频率过高而短路
t &= ~((0xff << 12) | (0x3f << 4) | (3 << 0)); //利用锁相环将12MHz倍频
t |= ((127 << 12) | (2 << 4) | (1 << 0)); //配置fclk频率大约为400Mhz
CLKDIVN |= ((2 << 1) | (1 << 0));//分频,配置HCLK为100MHz,HCLK为50MHz
MPLLCON = t;//将所有频率配置好再进行设置,防止器件被烧坏
}
unsigned char buffer[128];//存储pc给s3c2440发送,s3c2440接收到的字符串
unsigned char tmpbuffer[128];
unsigned int pos;//已经收到字符的个数,下一个要收到字符的位置
void uart0_handler(void)
{
if (SUBSRCPND & (1 << 0))//如果UART0接收到了数据
{
buffer[pos++] = URXH0;
}
SUBSRCPND = SUBSRCPND;
}
void init_uart0(void)
{
unsigned int t = 0;
GPHCON &= ~(0x0f << 4);
GPHCON |= ((2 << 6) | (2 << 4));//设置中断模式,串口电路引脚寄存器功能
t = ULCON0; //9600 n 8 1 波特率? 校验位? 数据位? 停止位
t &= ~(1 << 6);//不使用红外模式
t &= ~(7 << 3);//无奇偶校验
t &= ~(1 << 2);//每帧 1 个停止位
t |= (3 << 0);//每帧用于发送或接收的数据位的个数8位
ULCON0 = t;
t = UCON0; //s3c2440给电脑发送数据用轮询 电脑给s3c2440发送数据,s3c2440接收数据触发中断
t &= ~(3 << 10);//选PCLK给 UART 波特率
t &= ~(3 << 8);//发送接收方式改为脉冲方式
t &= ~(0x0f << 4);// 都设置为普通模式
t &= ~(0x0f << 0);
t |= (0x05 << 0);//设置UART模式发送轮询 接收模式为中断
UCON0 = t;
INTSUBMSK &= ~(1 << 0);//uart子中断改为可服务状态
enable_irq(IRQ_UART0);//配置中断为IRQ模式,让中断处于可服务模式 //配置接收的中断
register_irq(IRQ_UART0 ,uart0_handler);
UBRDIV0 = 325;//波特率分频寄存器 50000000/9600/16-1约等于325
pos = 0;
}
void uart_send_char(unsigned char ch)
{
UTXH0 = ch; // UART0 要发送的数据 UART 发送缓冲 寄存器
while (0 == (UTRSTAT0 & (1 << 2)));//数据发完的标志 UART TX/RX 状态 寄存器
}
void send_buffer(const char *p, unsigned int len)
{
unsigned int i = 0;
for (i = 0; i < len; ++i)
{
uart_send_char(*p++);
}
}
int parse(const char *p, unsigned int len)//分析上位机pc端发送的信息
{
int i = 0;
int n = 0;
unsigned char tmpnum = 0;
if (p[0] != 0xaa || p[len-1] != 0x0D)//判断起始校验位
{
n = 0;
}
if (p[1] != ADDRESS) //判断是否为正确的下位机
{
n = 0;
}
for (i = 0; i < 8; i++)
{
tmpnum += p[i];
}
if (p[8] != tmpnum) //判断校验位是否正确
{
n = 0;
}
if (0x01 == p[2])//调频
{
n = 1;
}
else if (0x02 == p[2]) //点灯
{
n = 2;
}
return n;
}
int main(void)
{
float f = 0;
int ret = 0;
int i = 0;
unsigned led = 0;
init_wdt();
init_led();
init_clk();
init_delay();
init_uart0();
init_pwm0();
while (1)
{
if (pos != 0)//收到数据了
{
mdelay(100);//让数据接收完成, 若收100字节,即1000比特,要1000/9600=0.1s=100ms
ret = parse((const char *)buffer, pos);
if (1 == ret)//调频 AA 08 01 04 00 00 00 3F F6 0D
{
buffer[8] = '\0';
f = *((float *)buffer[4]);
set_duty_ratio(f);
buffer[8] = 0xf6;
for (i = 0; i < 3; i++)
{
tmpbuffer[i] = buffer[i];
}
tmpbuffer[3] = 0x01;
tmpbuffer[4] = 0x01;
tmpbuffer[5] = buffer[8];
tmpbuffer[6] = buffer[9];
tmpbuffer[7] = '\0';
send_buffer((const char *)tmpbuffer, 7);
}
else if (2 == ret)//点灯 AA 08 02 04 00 00 00 3F B9 0D
{
buffer[8] = '\0';
led = buffer[7];
ledon(led);
buffer[8] = 0xB9;
for (i = 0; i < 3; i++)
{
tmpbuffer[i] = buffer[i];
}
tmpbuffer[3] = 0x01;
tmpbuffer[4] = 0x01;
tmpbuffer[5] = buffer[8];
tmpbuffer[6] = buffer[9];
tmpbuffer[7] = '\0';
send_buffer((const char *)tmpbuffer, 7);
}
else //发送失败
{
for (i = 0; i < 3; i++)
{
tmpbuffer[i] = buffer[i];
}
tmpbuffer[3] = 0x00;
tmpbuffer[4] = 0x00;
tmpbuffer[5] = buffer[8];
tmpbuffer[6] = buffer[9];
tmpbuffer[7] = '\0';
send_buffer((const char *)tmpbuffer, 7);
}
pos = 0;
memset(buffer, 0, sizeof(buffer));
memset(tmpbuffer, 0, sizeof(tmpbuffer));
}
}
}
1. TCON 2 定时器输出变相开关 0刚开始低电平、 1刚开始低电平
2. 串口是一种串行
串行不一定是串口
串行:一次收发一个比特
3. 传一个字节,8位+1位起始位+1位停止位,传输一个字节即传输十个比特
9600波特率为一秒传输960个字节
9600 n 8 1
波特率 校验位 数据位 停止位
U17作用:将TTL转化为标准RS232
4. UART控制寄存器
TX RX
脉冲:数据收发完产生中断
电平:数据收发过程中产生中断
5. i++和++i(++i效率高)
若i = 2;
++i printf打印i和++i都是2+1=3
i++(会开辟临时变量保存i++) printf打印i为3,i++为2
6. PC端(电脑)上位机
板子下位机
7. CRC校验算法
8. modbus
成功01失败00
1. 计数器监视寄存器查看计数器从开始减到目前的数字,查看当前的数字减到了多少
modbus重点!!!!!!!!!!!CRC