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

推荐订阅源

奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
C
CXSECURITY Database RSS Feed - CXSecurity.com
D
Docker
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
Jina AI
Jina AI
小众软件
小众软件
Last Week in AI
Last Week in AI
Hugging Face - Blog
Hugging Face - Blog
博客园 - 三生石上(FineUI控件)
宝玉的分享
宝玉的分享
美团技术团队
爱范儿
爱范儿
V
V2EX
大猫的无限游戏
大猫的无限游戏
人人都是产品经理
人人都是产品经理
J
Java Code Geeks
博客园 - 司徒正美
博客园 - 叶小钗
S
SegmentFault 最新的问题
量子位
S
Secure Thoughts
月光博客
月光博客
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
O
OpenAI News
L
LINUX DO - 最新话题
罗磊的独立博客
SecWiki News
SecWiki News
雷峰网
雷峰网
Recent Announcements
Recent Announcements
V2EX - 技术
V2EX - 技术
T
Tailwind CSS Blog
H
Hacker News: Front Page
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
云风的 BLOG
云风的 BLOG
Schneier on Security
Schneier on Security
T
The Blog of Author Tim Ferriss
IT之家
IT之家
博客园 - 聂微东
腾讯CDC
N
News | PayPal Newsroom
P
Proofpoint News Feed
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The GitHub Blog
The GitHub Blog
Hacker News: Ask HN
Hacker News: Ask HN
aimingoo的专栏
aimingoo的专栏
Webroot Blog
Webroot Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
K
Kaspersky official 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);

}