惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Last Watchdog
The Last Watchdog
S
Securelist
T
Threat Research - Cisco Blogs
Forbes - Security
Forbes - Security
AI
AI
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Attack and Defense Labs
Attack and Defense Labs
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Know Your Adversary
Know Your Adversary
P
Privacy International News Feed
W
WeLiveSecurity
P
Palo Alto Networks Blog
O
OpenAI News
V2EX - 技术
V2EX - 技术
H
Heimdal Security Blog
L
Lohrmann on Cybersecurity
NISL@THU
NISL@THU
T
Tor Project blog
T
Threatpost
G
GRAHAM CLULEY
T
The Exploit Database - CXSecurity.com
云风的 BLOG
云风的 BLOG
人人都是产品经理
人人都是产品经理
A
Arctic Wolf
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Latest news
Latest news
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Tenable Blog
量子位
L
LINUX DO - 最新话题
Webroot Blog
Webroot Blog
F
Fortinet All Blogs
C
CERT Recently Published Vulnerability Notes
Hacker News: Ask HN
Hacker News: Ask HN
U
Unit 42
T
Tailwind CSS Blog
WordPress大学
WordPress大学
N
News | PayPal Newsroom
C
CXSECURITY Database RSS Feed - CXSecurity.com
N
Netflix TechBlog - Medium
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Stack Overflow Blog
Stack Overflow Blog
Cloudbric
Cloudbric
C
Check Point Blog
V
Visual Studio Blog
The GitHub Blog
The GitHub Blog
The Hacker News
The Hacker News
B
Blog

博客园 - 易学

Control Panel Shortcuts 使用SerialPort及ZedGraph快速实现串口数据实时显示 基于.NET Compact Framework的实时曲线绘制控件 在Windows mobile 6.0模拟器中实现蓝牙数据采集 Firmata解析 多线程环境下的UI异步操作 定制带有模拟器且支持ActiveSync调试的WINCE5.0 SDK WinCE下动态显示绘图控件 XPE及CE系统对比 西溪湿地(摘录) - 易学 - 博客园 当前电子鼻系统数据处理中常用的模式识别技术 各大公司样片申请指南 数字万用表集成块的代换技巧 AD855x系列在微弱信号检测中的应用 测试Live Writer能否直接发图片 Radial 射线 昆明理工大学博士、硕士论文撰写规范 “共轭变换”图像处理算法在FPGA 上实现的研究
基于LMS8962的跑马灯教学程序——定时器、串口及GPIO的使用
易学 · 2010-06-18 · via 博客园 - 易学

一、电路原理图

从图中可知,各LED是逢GPIO口为0,即低电平时亮,为1,即高电平时灭,呈反逻辑。由于四灯接至引脚号连续的GPIOA口的PIN2~PIN5,因此,可以方便地一次性控制四灯的工作状态。因此,首先定义LEDs为四个引脚的组合,代码如下:

#define LEDs GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2

控制代码如下:

GPIOPinWrite(GPIO_PORTA_BASE, LEDs, temp<<2);

此处,temp左移2位,是使得temp的低四位可以对齐至PIN5,PIN4,PIN3,PIN2。

二、功能要求

(1)闪灭时间1s

(2)起始状态LED3、LED4、LED5、LED6全灭;

(3)走马灯流程

a.LED3亮(其他三灯灭)->LED4亮(其他三灯灭)->

LED5亮(其他三灯灭)->LED6亮(其他三灯灭)

b.四灯由灭到亮,由亮到灭闪烁4次

c.LED6亮(其他三灯灭)->LED5亮(其他三灯灭)->

LED4亮(其他三灯灭)->LED3亮(其他三灯灭)

d.继续流程b

如若定义状态编码如下:

LED6 

LED5 

LED4 

LED3 

MSB(0,灭;1,亮)

(0,灭;1,亮)

(0,灭;1,亮)

(0,灭;1,亮)LSB

例如:状态——LED6灭,LED5灭,LED灭,LED3亮,对应编码0001。

则每秒的状态如下所示:

三、功能实现

3.1 使用查询方式

从功能要求中,可以看到,此走马灯可以分为三种基本状态:

  1. LED点亮顺序由小到大(即LED3->LED4->…………)

  2. 四灯同闪4次

  3. LED点亮顺序由大到小(即LED6->LED5->…………)

因此设计三个函数完成以上3项功能:

3.1.1 ShiftUp

void ShiftUp()

{

int i = 0;

unsigned char temp = 0;

for(i = 0; i <=3; i++){

temp = ~(0x01<<i);

GPIOPinWrite(GPIO_PORTA_BASE, LEDs, temp<<2);

SysCtlDelay(1000* (TheSysClock / 3000)); // 延时约1s

}

}

3.1.2 ShiftDown

void ShiftDown()

{

int i = 0;

unsigned char temp = 0;

for(i = 0; i <=3; i++){

temp = ~(0x08>>i);

GPIOPinWrite(GPIO_PORTA_BASE, LEDs, temp<<2);

SysCtlDelay(1000* (TheSysClock / 3000)); // 延时约1s

}

}

3.1.3 Blinky

void Blinky(){

int i = 0;

for(i = 0; i <=3; i++)

{

GPIOPinWrite(GPIO_PORTA_BASE, LEDs, 0x00<<2);//

SysCtlDelay(1000* (TheSysClock / 3000)); // 延时约1s

GPIOPinWrite(GPIO_PORTA_BASE, LEDs, 0xFF<<2);//

SysCtlDelay(1000* (TheSysClock / 3000)); // 延时约1s

}

}

3.1.4 主程序

void main()

{

SysClkInit();

PortAInit();

while(1)

{

ShiftUp();

Blinky();

ShiftDown();

Blinky();

}

}

3.2 使用定时器中断方式

3.2.1 初始化Timer0A

void TimerAInit()
{

						/*  使能定时器0外设  */
					
    SysCtlPeripheralEnable( SYSCTL_PERIPH_TIMER0 );

						/*  使能全局中断  */
					
    IntMasterEnable();

						/*  使能Timer0中断  */
					
    GPIOPinTypeTimer(TIMER0_BASE, TIMER_A);

						/*  设置定时器0为周期触发模式   */
					
    TimerConfigure(TIMER0_BASE,    TIMER_CFG_32_BIT_PER);

						/*  设置定时器装载值:定时1/2  */
					
    TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet());

						/*  设置定时器为溢出中断  */
					
    TimerIntEnable(TIMER0_BASE,    TIMER_TIMA_TIMEOUT);

						/*  使能定时器0  */
					
    TimerEnable(TIMER0_BASE, TIMER_A);

						/*  使能定时器0外设  */
					
    IntEnable(INT_TIMER0A);                                             
}

3.2.2 Timer0A中断服务程序

void Timer0A_ISR (void)

{

unsigned char temp = 0;

/* 清除定时器0中断 */

TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

switch (status)

{

case 1:

temp = ~(0x01 << index);

index ++;

if(index == 4)

{

preStatus = 1;

status = 2;

index = 0;

}

break;

case 2:

if(index%2)

temp = ~(0x00);

else

temp = ~(0x0f);

index ++;

if(index == 8)

{

if(preStatus == 1)

status = 3;

else

status = 1;

index = 0;

}

break;

case 3:

temp = ~(0x08 >> index);

index ++;

if(index == 4)

{

preStatus = 3;

status = 2;

index = 0;

}

break;

default:

status = 1;

index = 0;

break;

}

GPIOPinWrite(GPIO_PORTA_BASE, LEDs, temp<<2);

/* 使能定时器0 */

TimerEnable(TIMER0_BASE, TIMER_A);

}

由于中断服务程序每秒进入一次,因此,需要记录每次进入中断服务时LED运行的状态,该状态由走马灯运行阶段status,某运行阶段累计次数index,以及preStatus决定。此三个变量定义为全局变量,如下所示:

int status = 1;

int preStatus = 1;

int index = 0;

状态之间的切换顺序为:

状态1(LED从小到大依次闪过)                                            ——>

状态2(LED闪烁4次后根据preStatus的值选择进入状态3或状态1)            ——>

状态3(LED从大到小依次闪过)

3.3 发送状态编码

3.3.1 初始化UART0

#define UART0_PIN     GPIO_PIN_0 | GPIO_PIN_1

void Uart0Init()

{

/* 使能UART外设 */

SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

/* 使能GPIOA外设 */

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

/* 配置UART功能脚 */

/* 设置GPIOA0A1UART引脚 */

/* (A0->RXD,A1->TXD) */

GPIOPinTypeUART(GPIO_PORTA_BASE, UART0_PIN);

/* 配置UART 9600波特率 8-N-1模式发送数据 */

UARTConfigSet(UART0_BASE, 9600, (UART_CONFIG_WLEN_8 |

UART_CONFIG_STOP_ONE |

UART_CONFIG_PAR_NONE));

}

3.3.2 发送字符串

void UartPuts(const char *s)

{

while(*s != '\0')

{

UARTCharPut(UART0_BASE, *(s++));

}

}

3.3.3 Timer0A_ISR

void Timer0A_ISR (void)

{

char buffer[8];

unsigned char bit4;

unsigned char bit3;

unsigned char bit2;

unsigned char bit1;

unsigned char temp = 0;

/* 清除定时器0中断 */

TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

switch (status)

{

case 1:

temp = ~(0x01 << index);

index ++;

if(index == 4)

{

preStatus = 1;

status = 2;

index = 0;

}

break;

case 2:

if(index%2)

temp = ~(0x00);

else

temp = ~(0x0f);

index ++;

if(index == 8)

{

if(preStatus == 1)

status = 3;

else

status = 1;

index = 0;

}

break;

case 3:

temp = ~(0x08 >> index);

index ++;

if(index == 4)

{

preStatus = 3;

status = 2;

index = 0;

}

break;

default:

status = 1;

index = 0;

break;

}

GPIOPinWrite(GPIO_PORTA_BASE, LEDs, temp<<2);

/* 取出temp各位,组成位字符串 */

bit4 = ((~temp)&0x08)>>3;

bit3 = ((~temp)&0x04)>>2;

bit2 = ((~temp)&0x02)>>1;

bit1 = ((~temp)&0x01)>>0;

sprintf(buffer, "%d%d%d%d\r\n\0", bit4, bit3, bit2, bit1);

/* 发送位字符串 */

UartPuts(buffer);

/* 使能定时器0 */

TimerEnable(TIMER0_BASE, TIMER_A);

}