Martinsville, VA (SportsNetwork.com) - Denny Hamlin ended a 31-race winless streak in the Sprint Cup Series after beating Brad Keselowski in a fierce battle for the lead in the closing laps of Sunday's STP 500 at Martinsville Speedway.

Hamlin, who hails from nearby Chesterfield, Virginia, passed Matt Kenseth, his Joe Gibbs Racing teammate, for the lead with 28 laps to go. Keselowski, the winner of last weekend's race in Fontana, California, challenged Hamlin for the top spot during the last 20 laps of this 500-lap race.

Coming out of the final turn of the last lap, Keselowski nudged Hamlin from behind in an attempt to take the lead. Hamlin wiggled slightly but held on to it, beating Keselowski to the finish line by just 0.186 seconds for his 25th career Sprint Cup win but his first since last May at Talladega.

"I did everything I could other than wreck (Hamlin)," Keselowski said. "I hit him pretty good a couple of times, so he did a good job and he chose not to wreck, which I give him credit for it."

It's also the fifth time Hamlin has won a Cup race at Martinsville, which is the oldest and smallest track -- 0.526 miles in length -- in NASCAR's premier series.

"I feel like I missed out on so many grandfather clocks (trophy for winning a Martinsville race) here because of mechanical issues and such," Hamlin said. "We just weren't going to be denied today, and hats off to Brad (Keselowski). He had an option and he took the latter. I thank him for that."

Hamlin, the driver of the No. 11 Toyota for JGR, led a total of 91 laps. He grabbed the top spot for the first time on lap 148, but shortly after during a round of pit stops under caution, he was penalized for a tire that got away from his pit stall. The penalty dropped him far back in the field.

"We had a very fast car, but obviously some pit road issues, but we overcame it," he said. "We got luckily on the inside line on that last restart and that was the key for us to win. (Crew chief) Dave (Rogers) and the guys gave me a car I could win with, and we got it done."

Hamlin's victory happened in what has been a difficult week for JGR. On Wednesday, the team revealed that its president, J.D. Gibbs, is being treated for symptoms impacting areas of his brain function, including speech and processing issues. Gibbs' doctors believe the complications he has experienced were triggered by head injuries likely suffered earlier in life, but no specific injury has been referenced or identified. His presence at the racetrack will be limited. He was not present at Martinsville.

"J.D. is the one who gave me my start 10 years ago, and I can't be prouder to put Gibbs Racing back in victory lane," Hamlin said. "They've been with me for so long and believe in me."

Neither JGR nor Toyota has been to victory lane for a Sprint Cup points race since Hamlin's victory at Talladega nearly a year ago.

During Hamlin's post-race press conference, team owner Joe Gibbs noted that he had his son, J.D., in mind throughout the race, especially when Hamlin took the checkered flag.

"For me, it was emotional and thinking about J.D. and all that he means to our team, so it was a big week for us, but a great finish to a story there," Gibbs said.

Keselowski's second-place run marked his best finish at Martinsville.

Joey Logano, the pole sitter, finished third after winning Saturday's Camping World Truck Series race here. Logano dominated in the early going, leading 107 of the first 133 laps, but he had to rebound from a spin which occurred on lap 219 when he made contact with Michael Annett.

"We had a decent race car, and we recovered from the spin halfway through the race, and we worked our way back and slowly but surely got ourselves back in the top-three," Logano said.

Kenseth ended up finishing fourth, while David Ragan, substituting for the injured Kyle Busch in JGR's No. 18 car, placed fifth. Martin Truex Jr. and Danica Patrick were sixth and seventh, respectively.

Patrick set a record for the highest-finishing female in a race at Martinsville. Her finish here was only one position behind her Sprint Cup career-best run of sixth, accomplished last August at Atlanta.

"It feels good," said Patrick, the driver of the No. 10 Chevrolet for Stewart- Haas Racing. "This is the kind of stuff we need - a new group together. We need these ego boosts every now and again. So it was fun racing, and we have to do it more often."

Kevin Harvick's attempt to finish in the top-two in nine consecutive races came up short with an eighth-place run. Harvick had placed either first or second in the last three races last year and the first five events this season. He led the most laps in this race with 154.

Jeff Gordon and Jamie McMurray completed the top-10. Gordon, who is in his final season of Sprint Cup competition, held the lead with less than 40 laps to go, but the four-time series champion was penalized for speeding onto pit road during the 16th and final caution. He had fallen back to 21st for the last restart.

"Oh, my gosh, I'm so disappointed in myself," said Gordon, an eight-time race winner at Martinsville. "I know I was pushing the limit. I didn't think I had done anything different than I had all day long when I was behind other guys, so we've got to look at that. I'm very, very disappointed. I felt like we finally got the car, got ourselves in a position to win that race."

Chase Elliott, who is replacing Gordon in the No. 24 Hendrick Motorsports Chevrolet next season, finished 38th in his first career Sprint Cup start. Elliott suffered rear-end damage to his No. 25 Hendrick car when he was bumped around following a restart early in the race. He spent 70 laps in the garage area for repairs. The 2014 Xfinity Series champion is expected to drive the No. 25 in four more Cup events this year.

"Welcome to Cup, got some work to do!" Elliott tweeted after the race.

Regan Smith drove Kyle Larson's No. 42 Chip Ganassi Racing Chevrolet to a 16th-place finish. Larson had to miss this race due to additional medical tests following his fainting spell during an autograph session at this track on Saturday.