思考
如果只给你不限制个数的IO口,如何实现一个控制器给另外一个控制器传输一个数据(一组数据)?
串口通信
是指使用一条数据线,将数据一位一位地依次传输,每一位数据占据一个固定的时间长度。其只需要少数几条线就可以在系统间交换信息,特别适用于计算机与计算机、计算机与外设之间的远距离通信。
按传输方向分类:
单工:任何时候数据只能朝一个方向传输
半双工:数据可以向两个方向传输,但任何同一时刻只能朝一个方向传输
全双工:数据可以同时向两个方向传输
同步通信是一种连续串行传送数据的通信方式,一次通信只传送一帧信息。这里的信息帧与异步通信中的字符帧不同,通常含有若干个数据字符。
它们均由同步字符、数据字符和校验字符(CRC)组成。其中同步字符位于帧开头,用于确认数据字符的开始。数据字符在同步字符之后,个数没有限制,由所需传输的数据块长度来决定;校验字符有1到2个,用于接收端对接收到的字符序列进行正确性的校验。同步通信的缺点是要求发送时钟和接收时钟保持严格的同步。
如:SPI I2C
异步通信中,在异步通信中有两个比较重要的指标:字符帧格式和波特率。数据通常以字符或者字节为单位组成字符帧传送。字符帧由发送端逐帧发送,通过传输线被接收设备逐帧接收。发送端和接收端可以由各自的时钟来控制数据的发送和接收,这两个时钟源彼此独立,互不同步。
接收端检测到传输线上发送过来的低电平逻辑"0"(即字符帧起始位)时,确定发送端已开始发送数据,每当接收端收到字符帧中的停止位时,就知道一帧字符已经发送完毕。
如:rs485 rs232
串口异步通信的重要参数:
波特率: bps (bit per second)
数据位的个数: 5 6 7 8
校验方式: 奇校验 偶校验 无校验
停止位: 1bit 2bit
异步串行数据的一般格式是:
起始位+数据位+停止位,(8-N-1格式) 其中起始位1 位,数据位可以是5、6、7、8位,停止位可以是1、1.5、2位。
串行接口标准
电子工业协会(EIA)制定并发布了串行数据通信接口标准
RS-232、RS-422、RS-485
RS-232是目前最常用的一种串行接口标准
=======================
2:RxD:接收管脚
3:TxD:发送管脚
5:接地
=======================
数据终端设备(DTE)和数据通信设备(DCE)之间串行二进制数据交换接口技术标准
标准主要规定了电气特性,机械特性。
举例:RS-232电平的电气特性:
EIA电平(串口)
逻辑1:-3V~-15V
逻辑0:+3V~+15V
===========================
扩展:
TTL电平(TPAD)
逻辑1:+2V~+5V
逻辑0:+0V~+0.8V
接收数据:EIA->TTL 232转TTL
发送数据:TTL->EIA TTL转232
===========================
并行通信:在计算机和终端之间的数据传输通常是靠电缆或信道上的电流或电压变化实现的。如果一组数据的各数据位在多条线上同时被传输,这种传输方式称为并行通信。
C语言实现S3C2451 UART功能:
一、直接操作寄存器
#ifndef _S3C2451_UART_H
#define _S3C2451_UART_H
#include "typedef.h"
/**
*设置数据位长度、起始位、停止位、校验位
**/
#define ULCON0 (*(volatile unsigned long*)0x50000000)
#define UCON0 (*(volatile unsigned long*)0x50000004)
#define UFCON0 (*(volatile unsigned long*)0x50000008)
#define UMCON0 (*(volatile unsigned long*)0x5000000C)
#define UTRSTAT0 (*(volatile unsigned long*)0x50000010)
#define UERSTAT0 (*(volatile unsigned long*)0x50000014)
#define UFSTAT0 (*(volatile unsigned long*)0x50000018)
#define UMSTAT0 (*(volatile unsigned long*)0x5000001C)
#define UTXH0 (*(volatile unsigned long*)0x50000020)
#define URXH0 (*(volatile unsigned long*)0x50000024)
#define UBRDIV0 (*(volatile unsigned long*)0x50000028)
#define UDIVSLOT0 (*(volatile unsigned long*)0x5000002C)
/**
* 寄存器函数声明
**/
//extern void UART_INIT(void);
//extern void UART_SendChar(U8 data);
//extern void UART_SendString(U8* data);
//extern U8 UART_RecvChar(void);
#endif
/**
*直接操作寄存器,初始化串口
**/
void UART_INIT(void)
{
//配置数据位长度,停止位,校验位ULCON0
ULCON0 |= 0x3; //8位数据位
ULCON0 &= ~(0x4); //
ULCON0 &= ~(0x38);
UBRDIV0 = 34;
UDIVSLOT0 = 0xDFDD;
}
/**
*串口发送一个字节数据
**/
void UART_SendChar(U8 data)
{
UTXH0 = data;
while((UTRSTAT0 & (0x4)) != 0);
}
/**
*串口发送一个字符串
**/
void UART_SendString(U8* data)
{
U8 i = 0;
while(data[i] != '\0')
{
UTXH0 = data[i];
i++;
}
while((UTRSTAT0 & (0x4)) != 0);
}
/**
*串口接收一个数据
**/
U8 UART_RecvChar(void)
{
return URXH0;
}
#include "main.h"
void delay(volatile int count)
{
while (count--);
}
void delay_ms(unsigned int xms)
{
unsigned int j;
for(; xms > 0; xms--)
{
for(j = 500; j > 0; j --);
}
}
void Main(void)
{
U8 ch;
LED_INIT();
while(1)
{
UART_SendString("Hello");
delay_ms(1000);
UART_SendString(" world\n");
delay_ms(1000);
while((ch = UART_RecvChar()) == 0);
switch(ch)
{
case 'a':
{
GPIO_WriteBit(GPIOA, GPIO_Pin_26, BIT_RESET);
break;
}
case 'b':
{
GPIO_WriteBit(GPIOA, GPIO_Pin_25, BIT_RESET);
break;
}
case 'c':
{
GPIO_WriteBit(GPIOB, GPIO_Pin_5, BIT_RESET);
break;
}
case 'd':
{
GPIO_WriteBit(GPIOB, GPIO_Pin_6, BIT_RESET);
break;
}
case 'e':
{
GPIO_WriteBit(GPIOB, GPIO_Pin_0, BIT_SET);
break;
}
case 'A':
{
GPIO_WriteBit(GPIOA, GPIO_Pin_26, BIT_SET);
break;
}
case 'B':
{
GPIO_WriteBit(GPIOA, GPIO_Pin_25, BIT_SET);
break;
}
case 'C':
{
GPIO_WriteBit(GPIOB, GPIO_Pin_5, BIT_SET);
break;
}
case 'D':
{
GPIO_WriteBit(GPIOB, GPIO_Pin_6, BIT_SET);
break;
}
case 'E':
{
GPIO_WriteBit(GPIOB, GPIO_Pin_0, BIT_RESET);
break;
}
}
}
}
二、编写C语言库函数实现UART
#ifndef _S3C2451_UART_H
#define _S3C2451_UART_H
#include "typedef.h"
typedef struct{
U32 ULCON;
U32 UCON;
U32 UFCON;
U32 UMCON;
U32 UTRSTAT;
U32 UERSTAT;
U32 UFSTAT;
U32 UMSTAT;
U32 UTXH;
U32 URXH;
U32 UBRDIV;
U32 UDIVSLOT;
}volatile *UART_MemMabPtr;
#define UART0_BASE_PTR ((UART_MemMabPtr)0x50000000)
#define UART1_BASE_PTR ((UART_MemMabPtr)0x50004000)
#define UART2_BASE_PTR ((UART_MemMabPtr)0x50008000)
#define UART3_BASE_PTR ((UART_MemMabPtr)0x5000C000)
/***串口枚举**/
typedef enum{
UART0 = 0,
UART1,
UART2,
UART3
}UART_Typedef;
/***数据位长度枚举**/
typedef enum{
DataLength_5Bit = 0,
DataLength_6Bit,
DataLength_7Bit,
DataLength_8Bit
}DataLength_Typedef;
/***停止位枚举**/
typedef enum{
STOP_ONE = 0,
STOP_TWO
}STOP_Typedef;
/***校验位枚举**/
typedef enum{
Parity_No = 0,
Parity_Odd = 4,
Parity_Even = 5,
Parity_One = 6,
Parity_Zero = 7
}PARITY_Typedef;
/***发送接收模式枚举**/
typedef enum{
Mode_rx = 0x1,
Mode_tx = 0x4,
Mode_rx_tx = 0x5
}MODE_Typedef;
typedef struct{
U32 brandrate;
DataLength_Typedef datalength;
STOP_Typedef stop;
PARITY_Typedef parity;
MODE_Typedef mode;
}UART_InitTypedef;
extern void UART_INIT(UART_Typedef uartx, UART_InitTypedef uart_inittypedef);
extern void UART_SendData(UART_Typedef uartx, U8* data);
extern U8 UART_RecvData(UART_Typedef uartx);
extern void My_Uart(U32 brandrate);
#endif
#include "s3c2451_uart.h"
UART_MemMabPtr const UART_BASE_PTR[4] = {
UART0_BASE_PTR,
UART1_BASE_PTR,
UART2_BASE_PTR,
UART3_BASE_PTR
};
/**函数名:UART_INIT
*参数:串口选择uartx,串口初始化结构体uart_inittypedef
*功能:初始化串口
**/
void UART_INIT(UART_Typedef uartx, UART_InitTypedef uart_inittypedef)
{
UART_BASE_PTR[uartx]->ULCON &= ~(0x7f); //清零
UART_BASE_PTR[uartx]->ULCON |= uart_inittypedef.datalength; //设置数据位
UART_BASE_PTR[uartx]->ULCON |= (uart_inittypedef.stop<<2); //设置停止位
UART_BASE_PTR[uartx]->ULCON |= (uart_inittypedef.parity<<3); //设置校验位
if(uart_inittypedef.brandrate == 115200)
{
UART_BASE_PTR[uartx]->UBRDIV = 34;
UART_BASE_PTR[uartx]->UDIVSLOT = 0xDFDD;
}
UART_BASE_PTR[uartx]->UCON &= ~(0xf);
if(uart_inittypedef.mode == Mode_rx)
{
UART_BASE_PTR[uartx]->UCON |= Mode_rx;
}
if(uart_inittypedef.mode == Mode_tx)
{
UART_BASE_PTR[uartx]->UCON |= Mode_tx;
}
if(uart_inittypedef.mode == Mode_rx_tx)
{
UART_BASE_PTR[uartx]->UCON |= Mode_rx_tx;
}
}
/**函数名:UART_SendData
*参数:串口选择uartx, 串口发送数据data
*功能:通过串口发送数据
**/
void UART_SendData(UART_Typedef uartx, U8* data)
{
U8 i = 0;
while(data[i] != '\0')
{
UART_BASE_PTR[uartx]->UTXH = data[i];
i++;
}
while((UART_BASE_PTR[uartx]->UTRSTAT & (0x4)) != 0);
}
/**函数名:UART_RecvData
*参数:串口选择uartx
*返回值:通过串口读取的数据
*功能:通过串口读取数据
**/
U8 UART_RecvData(UART_Typedef uartx)
{
return UART_BASE_PTR[uartx]->URXH;
}
/**函数名:My_Uart
*参数:波特率brandrate
*功能:本人常用的串口初始化设置
**/
void My_Uart(U32 brandrate)
{
UART_InitTypedef uart_inittypedef;
uart_inittypedef.brandrate = brandrate; //波特率
uart_inittypedef.datalength = DataLength_8Bit;
uart_inittypedef.mode = Mode_rx_tx;
uart_inittypedef.parity = Parity_No;
uart_inittypedef.stop = STOP_ONE;
UART_INIT(UART0, uart_inittypedef);
}
#include "main.h"
void delay(volatile int count)
{
while (count--);
}
void delay_ms(unsigned int xms)
{
unsigned int j;
for(; xms > 0; xms--)
{
for(j = 500; j > 0; j --);
}
}
void Main(void)
{
U8 ch;
My_Uart(115200);
LED_INIT();
while(1)
{
UART_SendData(UART0, "Hello");
delay_ms(1000);
UART_SendData(UART0, " world\n");
delay_ms(1000);
while((ch = UART_RecvData(UART0)) == 0);
switch(ch)
{
case 'a':
{
GPIO_WriteBit(GPIOA, GPIO_Pin_26, BIT_RESET);
break;
}
case 'b':
{
GPIO_WriteBit(GPIOA, GPIO_Pin_25, BIT_RESET);
break;
}
case 'c':
{
GPIO_WriteBit(GPIOB, GPIO_Pin_5, BIT_RESET);
break;
}
case 'd':
{
GPIO_WriteBit(GPIOB, GPIO_Pin_6, BIT_RESET);
break;
}
case 'e':
{
GPIO_WriteBit(GPIOB, GPIO_Pin_0, BIT_SET);
break;
}
case 'A':
{
GPIO_WriteBit(GPIOA, GPIO_Pin_26, BIT_SET);
break;
}
case 'B':
{
GPIO_WriteBit(GPIOA, GPIO_Pin_25, BIT_SET);
break;
}
case 'C':
{
GPIO_WriteBit(GPIOB, GPIO_Pin_5, BIT_SET);
break;
}
case 'D':
{
GPIO_WriteBit(GPIOB, GPIO_Pin_6, BIT_SET);
break;
}
case 'E':
{
GPIO_WriteBit(GPIOB, GPIO_Pin_0, BIT_RESET);
break;
}
}
}
}