ARM结构体系5:串行通信(双线UART)和看门狗

 在通信领域内,有两种数据通信方式:并行通信和串行通信,串口的数据传输是以串行方式进行的,串口在数据通信中,一次只传输一个比特的数据,串行数据的传输速度用bps或波特率来描述。

常用术语:

1.单工(simplex):仅能进行一个方向的数据传输。

2.半双工(half duplex):数据可以在两个方向上进行传输,但这种传输绝对不能同时进行(同步)

3.全双工(full duplex):能够在两个方向同时进行数据的传输(异步)。

我们的开发板和PC之间输出数据都是靠高低电平来实现,我们就需要约定一个串口协议,包括起始位,停止位,数据长度,校验位(奇偶校验),以及bps,通过这个协议我们通过UART进行高低电平检测达到通信传输数据的目的。 

硬件流控制:

 来看看实际收发数据是如何进行的,首先我们发射端和接收端缓存区工作方式需要设置为轮询或中断或DMA(内存访问,不安全),并且为了防止数据发送产生粘包现象,我们需要对发送缓存区进行判空操作,对接受缓存区进行判满操作,可以通过UTRSTAT寄存器的状态来判断。

上图就是我们传输的全过程图,我们可以再芯片手册中找到对应的寄存器进行设置,最后我会通过一个代码实例来展示。

 可以看到在UTRSTAT寄存器的第1位第0位分别表示发送区和接收区的状态,通过位运算我们就可以判断当前发射区和接收区的状态,从而让CPU知道什么时候该写数据接数据。

现在我们可以通过在超级终端中输入对应的字符来控制led灯的亮和灭:

#include <string.h>
#include <stdio.h>
void delay(int m)
{
	int i, j;
	for(i = 0; i < m; i++)
		for(j = 0; j < 256; j++);
}

#define GPA1CON			*(volatile unsigned int *)0x11400020
#define ULCON			*(volatile unsigned int *)0x13820000
#define UBRDIV			*(volatile unsigned int *)0x13820028
#define UFRACVAL		*(volatile unsigned int *)0x1382002c
#define UCON			*(volatile unsigned int *)0x13820004
#define UTRSTAT			*(volatile unsigned int *)0x13820010
#define UTXH			*(volatile unsigned int *)0x13820020
#define URXH			*(volatile unsigned int *)0x13820024

#define GPX2CON			*(volatile  unsigned int *)0x11000c40
#define GPX2DAT			*(volatile  unsigned int *)0x11000c44

void led2_init()
{
	// GPX2CON = GPX2CON & 0x0fffffff | (1 << 28)
	GPX2CON	= GPX2CON & (~(0xf << 28)) | ( 0x1 << 28 );
}
void led2_on()
{
	GPX2DAT = GPX2DAT | (1 << 7);
}
void led2_off()
{
	GPX2DAT = GPX2DAT & (~(1 << 7));
}
void gpio_init()
{
	//设置GPA1_0复用 UART_2_RXD功能,GPA1_1复用 UART_2_TXD功能
	// GPA1CON	= GPA1CON & ( ~(0xff << 0)) | (0x2 << 0) | (0x2 << 4);
	GPA1CON	= GPA1CON & ( ~(0xff << 0)) | (0x22 << 0);
}
void uart_init()
{
	//设置串口协议:数据位(8)、停止位(1)、奇偶校验位(无): 0000011
	ULCON |= 0x3;
	//设置波特率:115200
	// DIV_VAL = (PCLK_UART)/ (bps *16) -1
	//         = 100MHZ	/ (115200*16)-1
	//         = 100000000 / 115200/16-1
	//         = 53.25
	// UBRDIV  = 53
	// UFRACVAL = 0.25*16 = 4
	UBRDIV = 53;
	UFRACVAL = 4;
	
	//设置发送和接受数据的 工作模式: 中断或轮询 0101
	UCON = 0x05;
}
void uart_send(char ch)
{
	// while( UTRSTAT & (0x1 << 1) != 0x2 );
	while( !(UTRSTAT & (0x1 << 1)) );
	UTXH = ch;
}
char uart_recv()
{
	// while( UTRSTAT & (0x1) != 1);
	while( !(UTRSTAT & (0x1)));
	return URXH & 0xff;
}

void send(char *p)
{
	while(*p){
		uart_send(*p++);
	}
}

int myStrcmp(char *s1, char *s2)
{

}

int main()
{
	char *p = "hello world";

	gpio_init();
	uart_init();
	led2_init();

	send(p);
	send("\r\n");
	int i = 0;
	while(1){
		char buf[12] = {0};
		for(i = 0; i < 12; i++){
			buf[i] = uart_recv();
			if( buf[i] == ' ')
				break;
			uart_send(buf[i]);
		}
		send("\r\n");
		if ( myStrcmp(buf, "led_on") == 0){
			led2_on();
		} else if( myStrcmp(buf, "led_off") == 0){
			led2_off();
		}
	}
}

主要还是通过芯片手册找到对应的寄存器进行相应的工作模式设置!!!

看门狗

看门狗,是一个定时器电路,一般有一个输入,叫喂狗,一个输出到MCU的RST端,MCU正常工作的时候,每隔一段时间输出一个信号到喂狗段,给WDT清零,如果超过规定的时间不喂狗,WDT定时超时,就会给出一个复位信号到MCU,让MCU复位,防止MCU死机,看门狗的作用就是防止程序发生死循环,或者说程序跑飞。

工作原理:

在系统运行以后就启动了看门狗的计数器,看门狗就会开始自动计数,到了一定的时间还不去喂狗,那么看门狗计数器就会溢出导致看门狗中断,造成系统复位。

一般我们需要对看门狗进行设置,需要通过下面这张图的步骤:

看一段代码:这段代码详细介绍了看门狗的设置过程。

void delay(int m)
{
	int i, j;
	for(i = 0; i < m; i++)
		for(j = 0; j < 256; j++);
}

#define GPD0CON			*(volatile  unsigned int *)0x114000a0
#define GPD0DAT			*(volatile  unsigned int *)0x114000a4
//蜂鸣器设置
void beep_init()
{
	GPD0CON	= GPD0CON & (~(0xf << 0)) | ( 0x1 << 0 );
}
void beep_on()
{
	GPD0DAT = GPD0DAT | (1 << 0);
}
void beep_off()
{
	GPD0DAT = GPD0DAT & (~(1 << 0));
}

/**
 *	wdt频率 = plck / 预分频 / 二分频
 *	定时长  = (比较寄存器值 - 计数寄存器值) / wdt频率
 *
 * */

#define WTCON		*(volatile unsigned int *)0x10060000
#define WTDAT		*(volatile unsigned int *)0x10060004
#define WTCNT		*(volatile unsigned int *)0x10060008

void wdt_init()
{
	//设置预分频值 255
	WTCON |= 0xff << 8;
	//设置二分频值 128
	WTCON |= 0x3 << 3;
	//设置 WTCNT 计数寄存器值 1000
	WTCNT = 10000;
	//设置 WTDAT 数据寄存器值
	WTDAT = 10000;
	//设置 超时 产生复位信号 0x1
	WTCON |= 0x1;
	//启动 wdt的 定时器
	WTCON |= 1 << 5;
}

int main()
{
	wdt_init();
	beep_init();
	while(1){
		//喂狗,内部自动刷新cnt寄存器
		//WTDAT = 10000; //只有超时触发终端的时候,向DAT寄存器写数据,会自动搬移到 CNT寄存器
		WTCNT = 10000;   //CNT未 溢出产生复位信号时,必须通过 CNT重新装载,才能保证不产生复位信号
		beep_on();
		delay(5);
		beep_off();
		delay(15);
	}
}

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值