02 TI CC2530的uart控制器

uart原理参考
uart接口:
发出数据时,就是根据波特率的位时间来改变tx脚的电平. 如二进制数据是’1’则用高电平表示, ‘0’则用低电平表示.
接收数据时,根据位时间来判断rx脚的电平, 如是高电平则表示’1’, 低电平表示’0’.

作这样的工作比较麻烦,要求也比较高。所以一般情况下, CPU芯片里都会提供uar控制器,用于帮我们根据要传输的数据自动控制tx脚的电平和判断rx脚的电平. 而我们只需要配置好uart控制器的波特率,数据位,校验位,停止位等设置后, 再把要发出的数据提交给uart控制器, 控制器就会自动控制tx脚电平来发出数据。 而且uart控制器也会自动判断rx脚的电平来接收数据,当控制器接收完整一个字节数据时,我们只需从控制器把数据读回去即可.

//
CC2530里有两个USART控制器. USART控制器可以选择作uart控制器使用,也可以作SPI控制器使用. 只能二选一.

这里写图片描述

/
每个uart控制器都会有tx, rx引脚,一般都是与GPIO口复用的.
这里写图片描述

如上图USART0作uart控制器时,可以选择”P0_2,P0_3” 或者”P1_4,P1_5”作rx,tx脚用。
这个选择可在配置寄存器PERCFG里设置:
这里写图片描述

其中第0位的值是关于IO口的选择.设0则使用”P0_2,P0_3”, 设1则使用”P1_4,P1_4”.
再看电路图:
这里写图片描述

板上已把P0_2, P0_3口接到uart转usb接口的芯片. 也就是硬件上已选择P0_2, P0_3作为uart0控制器的rx,tx脚了。 而且硬件上也把uart接口转换成usb接口,方便我们把它连接到PC.
/
因IO口可以选择作普通的IO口使用(即作输入/输出), 也可以选择由控制器来控制.
这里需要把P0_2, P0_3选择由uart控制器来控制.

这里写图片描述
也就在寄存器里的值的第2位和第3位设1

/
IO选择由uart控制器控制后,就剩下配置好控制器就可以传输数据了.

uart控制器的配置:

1) 控制相关的配置
这里写图片描述

U0CSR = (1<<7); // usart0 作uart控制器,不作spi控制器用. 状态位是用于检查工作状态的,检查后需清零,这里不用设置.

2) 8N1相关的配置:
这里写图片描述

U0UCR = 1<<1; // 8N1, 始启位用低电平,停止位用高电平

3) 波特率, 手册里提供了一个波特率的计算公式:
这里写图片描述

而且也提供了一个参考值的表:
这里写图片描述
如选择9600波特率,则BAUD_M的值为59, BAUD_E的值为8.
注意上面的参考值是以系统时钟为32Mhz来设置的,而系统的默认时钟是16Mhz, 所以需要把时钟提升到32Mhz. 也可以不提升时钟,只需把BAUD_E的值-1.

时钟配置的寄存器
这里写图片描述

  //把系统时钟信号从16MHz提升为32MHz
  CLKCONCMD &= ~(1<<6); //32Mhz source
  while (CLKCONSTA & (1<<6)) //等待配置生效

    ;
  CLKCONCMD &= ~7; //把最低3位清零,选择32MHz

这里写图片描述

  // 9600   BAND_M(59)  BAND_E(8)
  U0GCR = 8; //最低5位用于存放uart的波特率设置 的BAND_E
  U0BAUD = 59;

/
配置完成后, 就可以传输数据了:

发送数据时, 通过U0DBUF寄存器把要发送的一个字节数据提交给uart控制器,控制器再把数据通过控制IO口电平来发出.

void putchar(int ch)
{
    U0CSR &= ~(0xf<<1); //清除包含发送的4种状态
    U0DBUF = ch; //把要发出的一字节数据存放到U0DBUF寄存器
    while (!(U0CSR & (1<<1)))   //等到控制器获取到U0DUBF寄存器里的数据为止
          ; 

    if ('\n' == ch)  //如是发出的是换行号,还需要发出"\r"回到行首
      putchar('\r');
}

接收数据时, 通过判断控制器的状态确定是否已接收到数据,确认接收到后, 则读U0DBUF寄存器,把数据从控制器里取出.

int getchar()
{
  int ch;

  while (!(U0CSR & (1<<2))) //等到控制器接收到数据
        ;
  ch = U0DBUF; //读出数据
  //U0CSR &= ~(1<<2); //清除状态

#if 0   //在连接在linux系统上,是不会接收到"\n"符号的,只能接收到"\r". window上可以接收到"\n"
  if ('\r' == ch)
    ch = '\n';
#endif

  //putchar(ch); //如需要回显,可以去掉备注
  return ch;
}

///
通过uart接口发送命令控制蜂鸣器响的例子完整代码:


#include <iocc2530.h>


void putchar(int ch);
void puts(char *line);
int uart_init(void);
void delay(int val);
int getchar();
int gets(char *line);
int strcmp(char *s1, char *s2);
void main(void)
{
    char chs[200];
    // buzzer p0_7  active_low
    P0SEL &= ~(1<<7);
    P0DIR |= 1<<7;

//    P0 &= ~(1<<7);
    uart_init();

    while (1)
    {
       gets(chs);
       puts("got:");
       puts(chs);
       putchar('\n');
       if (0 == strcmp("bp_on", chs))
       {
           P0 &= ~(1<<7); // buzzer active;
       }
        if (0 == strcmp("bp_off", chs))
       {
           P0 |= (1<<7); // buzzer off;
       }        
    }
}

int strcmp(char *s1, char *s2)
{
    while ((*s1) && (*s2))
    {
        if ((*s1++) != (*s2++))
              break;
    }

    return *s1 - *s2;
}

int gets(char *line)
{
  int ch, i = 0;
  char *p = line;

  while (1)
  {
    ch = getchar();
    if ('\n' == ch)
      break;
    *p++ = ch;
  }
  *p = 0;

  puts("kk:");
  puts(line);
  putchar('\n');
  return p - line;
}

int getchar()
{
  int ch;

  while (!(U0CSR & (1<<2))) //等到控制器接收到数据
        ;
  ch = U0DBUF; //读出数据
  //U0CSR &= ~(1<<2); //清除状态

#if 0   //在连接在linux系统上,是不会接收到"\n"符号的,只能接收到"\r". window上可以接收到"\n"
  if ('\r' == ch)
    ch = '\n';
#endif

  //putchar(ch); //如需要回显,可以去掉备注
  return ch;
}

int uart_init(void)
{
  //从16Mhz时钟改成32M时钟
  CLKCONCMD &= ~(1<<6); //32Mhz source
  while (CLKCONSTA & (1<<6))
    ;
  CLKCONCMD &= ~7; //32Mhz

  
  // P0_2(RX)   P0_3(TX)

  //P0_2, P0_3设置为uart控制器来控制, 不是作通用的IO
  P0SEL |= (1<<2)|(1<<3);

  //uart0的tx,rx口可以选择 P0_2,P0_3 也可以选择 P1_4, P1_5
  //通过寄存器PERCFG来确定使用哪两个IO口 
  PERCFG &= ~1; //选择P0_2, P0_3作uart的rx,tx脚 

  U0CSR = (1<<7)|(1<<6); // usart0 作uart控制器,不作spi控制器用
  U0UCR = 0; // 8N1

  // U0GCR 是关于spi控制器的配置 ,这里作uart控制器,所以不用配
  // U0DBUF 用于把数据交给uart控制器发出,并把控制器接收到的数据取回

  //波特率设置 表   P151
  // 115200   BAND_M(216)  BAND_E(11)

  U0GCR = 11; //最低5位用于存放uart的波特率设置 的BAND_E
  U0BAUD = 216;
  //
  return 0;
}

void putchar(int ch)
{
    U0CSR &= ~(0xf<<1); //清除包含发送的4种状态
    U0DBUF = ch; //把要发出的一字节数据存放到U0DBUF寄存器
    while (!(U0CSR & (1<<1)))   //等到控制器获取到U0DUBF寄存器里的数据为止
          ; 

    if ('\n' == ch)  //如是发出的是换行号,还需要发出"\r"回到行首
      putchar('\r');
}

void puts(char *line)
{
  while (*line)
    putchar(*line++);
}

void delay(int val)
{
  int i, j;

  for (i = 0; i < val; i++)
  {
    for (j = 0; j < 533; j++)
        ;
  }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值